diff options
Diffstat (limited to 'security/nss/lib/certdb')
23 files changed, 0 insertions, 17852 deletions
diff --git a/security/nss/lib/certdb/.cvsignore b/security/nss/lib/certdb/.cvsignore deleted file mode 100644 index ec60123e5..000000000 --- a/security/nss/lib/certdb/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -nscertinit.c diff --git a/security/nss/lib/certdb/Makefile b/security/nss/lib/certdb/Makefile deleted file mode 100644 index 36524f56a..000000000 --- a/security/nss/lib/certdb/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -#! gmake -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -####################################################################### -# (1) Include initial platform-independent assignments (MANDATORY). # -####################################################################### - -include manifest.mn - -####################################################################### -# (2) Include "global" configuration information. (OPTIONAL) # -####################################################################### - -include $(CORE_DEPTH)/coreconf/config.mk - -####################################################################### -# (3) Include "component" configuration information. (OPTIONAL) # -####################################################################### - - - -####################################################################### -# (4) Include "local" platform-dependent assignments (OPTIONAL). # -####################################################################### - -include config.mk - -####################################################################### -# (5) Execute "global" rules. (OPTIONAL) # -####################################################################### - -include $(CORE_DEPTH)/coreconf/rules.mk - -####################################################################### -# (6) Execute "component" rules. (OPTIONAL) # -####################################################################### - - - -####################################################################### -# (7) Execute "local" rules. (OPTIONAL). # -####################################################################### - -export:: private_export - diff --git a/security/nss/lib/certdb/alg1485.c b/security/nss/lib/certdb/alg1485.c deleted file mode 100644 index ffdaf9cf9..000000000 --- a/security/nss/lib/certdb/alg1485.c +++ /dev/null @@ -1,1555 +0,0 @@ -/* alg1485.c - implementation of RFCs 1485, 1779 and 2253. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.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 "prprf.h" -#include "cert.h" -#include "certi.h" -#include "xconst.h" -#include "genname.h" -#include "secitem.h" -#include "secerr.h" - -typedef struct NameToKindStr { - const char * name; - unsigned int maxLen; /* max bytes in UTF8 encoded string value */ - SECOidTag kind; - int valueType; -} NameToKind; - -/* local type for directory string--could be printable_string or utf8 */ -#define SEC_ASN1_DS SEC_ASN1_HIGH_TAG_NUMBER - -/* Add new entries to this table, and maybe to function ParseRFC1485AVA */ -static const NameToKind name2kinds[] = { -/* IANA registered type names - * (See: http://www.iana.org/assignments/ldap-parameters) - */ -/* RFC 3280, 4630 MUST SUPPORT */ - { "CN", 64, SEC_OID_AVA_COMMON_NAME, SEC_ASN1_DS}, - { "ST", 128, SEC_OID_AVA_STATE_OR_PROVINCE, - SEC_ASN1_DS}, - { "O", 64, SEC_OID_AVA_ORGANIZATION_NAME, - SEC_ASN1_DS}, - { "OU", 64, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, - SEC_ASN1_DS}, - { "dnQualifier", 32767, SEC_OID_AVA_DN_QUALIFIER, SEC_ASN1_PRINTABLE_STRING}, - { "C", 2, SEC_OID_AVA_COUNTRY_NAME, SEC_ASN1_PRINTABLE_STRING}, - { "serialNumber", 64, SEC_OID_AVA_SERIAL_NUMBER,SEC_ASN1_PRINTABLE_STRING}, - -/* RFC 3280, 4630 SHOULD SUPPORT */ - { "L", 128, SEC_OID_AVA_LOCALITY, SEC_ASN1_DS}, - { "title", 64, SEC_OID_AVA_TITLE, SEC_ASN1_DS}, - { "SN", 64, SEC_OID_AVA_SURNAME, SEC_ASN1_DS}, - { "givenName", 64, SEC_OID_AVA_GIVEN_NAME, SEC_ASN1_DS}, - { "initials", 64, SEC_OID_AVA_INITIALS, SEC_ASN1_DS}, - { "generationQualifier", - 64, SEC_OID_AVA_GENERATION_QUALIFIER, - SEC_ASN1_DS}, -/* RFC 3280, 4630 MAY SUPPORT */ - { "DC", 128, SEC_OID_AVA_DC, SEC_ASN1_IA5_STRING}, - { "MAIL", 256, SEC_OID_RFC1274_MAIL, SEC_ASN1_IA5_STRING}, - { "UID", 256, SEC_OID_RFC1274_UID, SEC_ASN1_DS}, - -/* ------------------ "strict" boundary --------------------------------- - * In strict mode, cert_NameToAscii does not encode any of the attributes - * below this line. The first SECOidTag below this line must be used to - * conditionally define the "endKind" in function AppendAVA() below. - * Most new attribute names should be added below this line. - * Maybe this line should be up higher? Say, after the 3280 MUSTs and - * before the 3280 SHOULDs? - */ - -/* values from draft-ietf-ldapbis-user-schema-05 (not in RFC 3280) */ - { "postalAddress", 128, SEC_OID_AVA_POSTAL_ADDRESS, SEC_ASN1_DS}, - { "postalCode", 40, SEC_OID_AVA_POSTAL_CODE, SEC_ASN1_DS}, - { "postOfficeBox", 40, SEC_OID_AVA_POST_OFFICE_BOX,SEC_ASN1_DS}, - { "houseIdentifier",64, SEC_OID_AVA_HOUSE_IDENTIFIER,SEC_ASN1_DS}, -/* end of IANA registered type names */ - -/* legacy keywords */ - { "E", 128, SEC_OID_PKCS9_EMAIL_ADDRESS,SEC_ASN1_IA5_STRING}, - { "STREET", 128, SEC_OID_AVA_STREET_ADDRESS, SEC_ASN1_DS}, - { "pseudonym", 64, SEC_OID_AVA_PSEUDONYM, SEC_ASN1_DS}, - -/* values defined by the CAB Forum for EV */ - { "incorporationLocality", 128, SEC_OID_EV_INCORPORATION_LOCALITY, - SEC_ASN1_DS}, - { "incorporationState", 128, SEC_OID_EV_INCORPORATION_STATE, - SEC_ASN1_DS}, - { "incorporationCountry", 2, SEC_OID_EV_INCORPORATION_COUNTRY, - SEC_ASN1_PRINTABLE_STRING}, - { "businessCategory", 64, SEC_OID_BUSINESS_CATEGORY, SEC_ASN1_DS}, - - { 0, 256, SEC_OID_UNKNOWN, 0}, -}; - -/* Table facilitates conversion of ASCII hex to binary. */ -static const PRInt16 x2b[256] = { -/* #0x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #1x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #2x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #3x */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -/* #4x */ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #5x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #6x */ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #7x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #8x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #9x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #ax */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #bx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #cx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #dx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #ex */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -/* #fx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -#define IS_HEX(c) (x2b[(PRUint8)(c)] >= 0) - -#define C_DOUBLE_QUOTE '\042' - -#define C_BACKSLASH '\134' - -#define C_EQUAL '=' - -#define OPTIONAL_SPACE(c) \ - (((c) == ' ') || ((c) == '\r') || ((c) == '\n')) - -#define SPECIAL_CHAR(c) \ - (((c) == ',') || ((c) == '=') || ((c) == C_DOUBLE_QUOTE) || \ - ((c) == '\r') || ((c) == '\n') || ((c) == '+') || \ - ((c) == '<') || ((c) == '>') || ((c) == '#') || \ - ((c) == ';') || ((c) == C_BACKSLASH)) - - -#define IS_PRINTABLE(c) \ - ((((c) >= 'a') && ((c) <= 'z')) || \ - (((c) >= 'A') && ((c) <= 'Z')) || \ - (((c) >= '0') && ((c) <= '9')) || \ - ((c) == ' ') || \ - ((c) == '\'') || \ - ((c) == '\050') || /* ( */ \ - ((c) == '\051') || /* ) */ \ - (((c) >= '+') && ((c) <= '/')) || /* + , - . / */ \ - ((c) == ':') || \ - ((c) == '=') || \ - ((c) == '?')) - -/* RFC 2253 says we must escape ",+\"\\<>;=" EXCEPT inside a quoted string. - * Inside a quoted string, we only need to escape " and \ - * We choose to quote strings containing any of those special characters, - * so we only need to escape " and \ - */ -#define NEEDS_ESCAPE(c) \ - (c == C_DOUBLE_QUOTE || c == C_BACKSLASH) - -#define NEEDS_HEX_ESCAPE(c) \ - ((PRUint8)c < 0x20 || c == 0x7f) - -int -cert_AVAOidTagToMaxLen(SECOidTag tag) -{ - const NameToKind *n2k = name2kinds; - - while (n2k->kind != tag && n2k->kind != SEC_OID_UNKNOWN) { - ++n2k; - } - return (n2k->kind != SEC_OID_UNKNOWN) ? n2k->maxLen : -1; -} - -static PRBool -IsPrintable(unsigned char *data, unsigned len) -{ - unsigned char ch, *end; - - end = data + len; - while (data < end) { - ch = *data++; - if (!IS_PRINTABLE(ch)) { - return PR_FALSE; - } - } - return PR_TRUE; -} - -static void -skipSpace(const char **pbp, const char *endptr) -{ - const char *bp = *pbp; - while (bp < endptr && OPTIONAL_SPACE(*bp)) { - bp++; - } - *pbp = bp; -} - -static SECStatus -scanTag(const char **pbp, const char *endptr, char *tagBuf, int tagBufSize) -{ - const char *bp; - char *tagBufp; - int taglen; - - PORT_Assert(tagBufSize > 0); - - /* skip optional leading space */ - skipSpace(pbp, endptr); - if (*pbp == endptr) { - /* nothing left */ - return SECFailure; - } - - /* fill tagBuf */ - taglen = 0; - bp = *pbp; - tagBufp = tagBuf; - while (bp < endptr && !OPTIONAL_SPACE(*bp) && (*bp != C_EQUAL)) { - if (++taglen >= tagBufSize) { - *pbp = bp; - return SECFailure; - } - *tagBufp++ = *bp++; - } - /* null-terminate tagBuf -- guaranteed at least one space left */ - *tagBufp++ = 0; - *pbp = bp; - - /* skip trailing spaces till we hit something - should be an equal sign */ - skipSpace(pbp, endptr); - if (*pbp == endptr) { - /* nothing left */ - return SECFailure; - } - if (**pbp != C_EQUAL) { - /* should be an equal sign */ - return SECFailure; - } - /* skip over the equal sign */ - (*pbp)++; - - return SECSuccess; -} - -/* Returns the number of bytes in the value. 0 means failure. */ -static int -scanVal(const char **pbp, const char *endptr, char *valBuf, int valBufSize) -{ - const char *bp; - char *valBufp; - int vallen = 0; - PRBool isQuoted; - - PORT_Assert(valBufSize > 0); - - /* skip optional leading space */ - skipSpace(pbp, endptr); - if(*pbp == endptr) { - /* nothing left */ - return 0; - } - - bp = *pbp; - - /* quoted? */ - if (*bp == C_DOUBLE_QUOTE) { - isQuoted = PR_TRUE; - /* skip over it */ - bp++; - } else { - isQuoted = PR_FALSE; - } - - valBufp = valBuf; - while (bp < endptr) { - char c = *bp; - if (c == C_BACKSLASH) { - /* escape character */ - bp++; - if (bp >= endptr) { - /* escape charater must appear with paired char */ - *pbp = bp; - return 0; - } - c = *bp; - if (IS_HEX(c) && (endptr - bp) >= 2 && IS_HEX(bp[1])) { - bp++; - c = (char)((x2b[(PRUint8)c] << 4) | x2b[(PRUint8)*bp]); - } - } else if (c == '#' && bp == *pbp) { - /* ignore leading #, quotation not required for it. */ - } else if (!isQuoted && SPECIAL_CHAR(c)) { - /* unescaped special and not within quoted value */ - break; - } else if (c == C_DOUBLE_QUOTE) { - /* reached unescaped double quote */ - break; - } - /* append character */ - vallen++; - if (vallen >= valBufSize) { - *pbp = bp; - return 0; - } - *valBufp++ = c; - bp++; - } - - /* strip trailing spaces from unquoted values */ - if (!isQuoted) { - while (valBufp > valBuf) { - char c = valBufp[-1]; - if (! OPTIONAL_SPACE(c)) - break; - --valBufp; - } - vallen = valBufp - valBuf; - } - - if (isQuoted) { - /* insist that we stopped on a double quote */ - if (*bp != C_DOUBLE_QUOTE) { - *pbp = bp; - return 0; - } - /* skip over the quote and skip optional space */ - bp++; - skipSpace(&bp, endptr); - } - - *pbp = bp; - - /* null-terminate valBuf -- guaranteed at least one space left */ - *valBufp = 0; - - return vallen; -} - -/* Caller must set error code upon failure */ -static SECStatus -hexToBin(PLArenaPool *pool, SECItem * destItem, const char * src, int len) -{ - PRUint8 * dest; - - destItem->data = NULL; - if (len <= 0 || (len & 1)) { - goto loser; - } - len >>= 1; - if (!SECITEM_AllocItem(pool, destItem, len)) - goto loser; - dest = destItem->data; - for (; len > 0; len--, src += 2) { - PRInt16 bin = (x2b[(PRUint8)src[0]] << 4) | x2b[(PRUint8)src[1]]; - if (bin < 0) - goto loser; - *dest++ = (PRUint8)bin; - } - return SECSuccess; -loser: - if (!pool) - SECITEM_FreeItem(destItem, PR_FALSE); - return SECFailure; -} - -/* Parses one AVA, starting at *pbp. Stops at endptr. - * Advances *pbp past parsed AVA and trailing separator (if present). - * On any error, returns NULL and *pbp is undefined. - * On success, returns CERTAVA allocated from arena, and (*pbp)[-1] was - * the last character parsed. *pbp is either equal to endptr or - * points to first character after separator. - */ -static CERTAVA * -ParseRFC1485AVA(PRArenaPool *arena, const char **pbp, const char *endptr) -{ - CERTAVA *a; - const NameToKind *n2k; - const char *bp; - int vt = -1; - int valLen; - SECOidTag kind = SEC_OID_UNKNOWN; - SECStatus rv = SECFailure; - SECItem derOid = { 0, NULL, 0 }; - SECItem derVal = { 0, NULL, 0}; - char sep = 0; - - char tagBuf[32]; - char valBuf[384]; - - PORT_Assert(arena); - if (SECSuccess != scanTag(pbp, endptr, tagBuf, sizeof tagBuf) || - !(valLen = scanVal(pbp, endptr, valBuf, sizeof valBuf))) { - goto loser; - } - - bp = *pbp; - if (bp < endptr) { - sep = *bp++; /* skip over separator */ - } - *pbp = bp; - /* if we haven't finished, insist that we've stopped on a separator */ - if (sep && sep != ',' && sep != ';' && sep != '+') { - goto loser; - } - - /* is this a dotted decimal OID attribute type ? */ - if (!PL_strncasecmp("oid.", tagBuf, 4)) { - rv = SEC_StringToOID(arena, &derOid, tagBuf, strlen(tagBuf)); - } else { - for (n2k = name2kinds; n2k->name; n2k++) { - SECOidData *oidrec; - if (PORT_Strcasecmp(n2k->name, tagBuf) == 0) { - kind = n2k->kind; - vt = n2k->valueType; - oidrec = SECOID_FindOIDByTag(kind); - if (oidrec == NULL) - goto loser; - derOid = oidrec->oid; - break; - } - } - } - if (kind == SEC_OID_UNKNOWN && rv != SECSuccess) - goto loser; - - /* Is this a hex encoding of a DER attribute value ? */ - if ('#' == valBuf[0]) { - /* convert attribute value from hex to binary */ - rv = hexToBin(arena, &derVal, valBuf + 1, valLen - 1); - if (rv) - goto loser; - a = CERT_CreateAVAFromRaw(arena, &derOid, &derVal); - } else { - if (kind == SEC_OID_UNKNOWN) - goto loser; - if (kind == SEC_OID_AVA_COUNTRY_NAME && valLen != 2) - goto loser; - if (vt == SEC_ASN1_PRINTABLE_STRING && - !IsPrintable((unsigned char*) valBuf, valLen)) - goto loser; - if (vt == SEC_ASN1_DS) { - /* RFC 4630: choose PrintableString or UTF8String */ - if (IsPrintable((unsigned char*) valBuf, valLen)) - vt = SEC_ASN1_PRINTABLE_STRING; - else - vt = SEC_ASN1_UTF8_STRING; - } - - derVal.data = (unsigned char*) valBuf; - derVal.len = valLen; - a = CERT_CreateAVAFromSECItem(arena, kind, vt, &derVal); - } - return a; - -loser: - /* matched no kind -- invalid tag */ - PORT_SetError(SEC_ERROR_INVALID_AVA); - return 0; -} - -static CERTName * -ParseRFC1485Name(const char *buf, int len) -{ - SECStatus rv; - CERTName *name; - const char *bp, *e; - CERTAVA *ava; - CERTRDN *rdn = NULL; - - name = CERT_CreateName(NULL); - if (name == NULL) { - return NULL; - } - - e = buf + len; - bp = buf; - while (bp < e) { - ava = ParseRFC1485AVA(name->arena, &bp, e); - if (ava == 0) - goto loser; - if (!rdn) { - rdn = CERT_CreateRDN(name->arena, ava, (CERTAVA *)0); - if (rdn == 0) - goto loser; - rv = CERT_AddRDN(name, rdn); - } else { - rv = CERT_AddAVA(name->arena, rdn, ava); - } - if (rv) - goto loser; - if (bp[-1] != '+') - rdn = NULL; /* done with this RDN */ - skipSpace(&bp, e); - } - - if (name->rdns[0] == 0) { - /* empty name -- illegal */ - goto loser; - } - - /* Reverse order of RDNS to comply with RFC */ - { - CERTRDN **firstRdn; - CERTRDN **lastRdn; - CERTRDN *tmp; - - /* get first one */ - firstRdn = name->rdns; - - /* find last one */ - lastRdn = name->rdns; - while (*lastRdn) lastRdn++; - lastRdn--; - - /* reverse list */ - for ( ; firstRdn < lastRdn; firstRdn++, lastRdn--) { - tmp = *firstRdn; - *firstRdn = *lastRdn; - *lastRdn = tmp; - } - } - - /* return result */ - return name; - - loser: - CERT_DestroyName(name); - return NULL; -} - -CERTName * -CERT_AsciiToName(const char *string) -{ - CERTName *name; - name = ParseRFC1485Name(string, PORT_Strlen(string)); - return name; -} - -/************************************************************************/ - -typedef struct stringBufStr { - char *buffer; - unsigned offset; - unsigned size; -} stringBuf; - -#define DEFAULT_BUFFER_SIZE 200 - -static SECStatus -AppendStr(stringBuf *bufp, char *str) -{ - char *buf; - unsigned bufLen, bufSize, len; - int size = 0; - - /* Figure out how much to grow buf by (add in the '\0') */ - buf = bufp->buffer; - bufLen = bufp->offset; - len = PORT_Strlen(str); - bufSize = bufLen + len; - if (!buf) { - bufSize++; - size = PR_MAX(DEFAULT_BUFFER_SIZE,bufSize*2); - buf = (char *) PORT_Alloc(size); - bufp->size = size; - } else if (bufp->size < bufSize) { - size = bufSize*2; - buf =(char *) PORT_Realloc(buf,size); - bufp->size = size; - } - if (!buf) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - bufp->buffer = buf; - bufp->offset = bufSize; - - /* Concatenate str onto buf */ - buf = buf + bufLen; - if (bufLen) buf--; /* stomp on old '\0' */ - PORT_Memcpy(buf, str, len+1); /* put in new null */ - return SECSuccess; -} - -typedef enum { - minimalEscape = 0, /* only hex escapes, and " and \ */ - minimalEscapeAndQuote, /* as above, plus quoting */ - fullEscape /* no quoting, full escaping */ -} EQMode; - -/* Some characters must be escaped as a hex string, e.g. c -> \nn . - * Others must be escaped by preceding with a '\', e.g. c -> \c , but - * there are certain "special characters" that may be handled by either - * escaping them, or by enclosing the entire attribute value in quotes. - * A NULL value for pEQMode implies selecting minimalEscape mode. - * Some callers will do quoting when needed, others will not. - * If a caller selects minimalEscapeAndQuote, and the string does not - * need quoting, then this function changes it to minimalEscape. - */ -static int -cert_RFC1485_GetRequiredLen(const char *src, int srclen, EQMode *pEQMode) -{ - int i, reqLen=0; - EQMode mode = pEQMode ? *pEQMode : minimalEscape; - PRBool needsQuoting = PR_FALSE; - char lastC = 0; - - /* need to make an initial pass to determine if quoting is needed */ - for (i = 0; i < srclen; i++) { - char c = src[i]; - reqLen++; - if (NEEDS_HEX_ESCAPE(c)) { /* c -> \xx */ - reqLen += 2; - } else if (NEEDS_ESCAPE(c)) { /* c -> \c */ - reqLen++; - } else if (SPECIAL_CHAR(c)) { - if (mode == minimalEscapeAndQuote) /* quoting is allowed */ - needsQuoting = PR_TRUE; /* entirety will need quoting */ - else if (mode == fullEscape) - reqLen++; /* MAY escape this character */ - } else if (OPTIONAL_SPACE(c) && OPTIONAL_SPACE(lastC)) { - if (mode == minimalEscapeAndQuote) /* quoting is allowed */ - needsQuoting = PR_TRUE; /* entirety will need quoting */ - } - lastC = c; - } - /* if it begins or ends in optional space it needs quoting */ - if (!needsQuoting && srclen > 0 && mode == minimalEscapeAndQuote && - (OPTIONAL_SPACE(src[srclen-1]) || OPTIONAL_SPACE(src[0]))) { - needsQuoting = PR_TRUE; - } - - if (needsQuoting) - reqLen += 2; - if (pEQMode && mode == minimalEscapeAndQuote && !needsQuoting) - *pEQMode = minimalEscape; - return reqLen; -} - -static const char hexChars[16] = { "0123456789abcdef" }; - -static SECStatus -escapeAndQuote(char *dst, int dstlen, char *src, int srclen, EQMode *pEQMode) -{ - int i, reqLen=0; - EQMode mode = pEQMode ? *pEQMode : minimalEscape; - - /* space for terminal null */ - reqLen = cert_RFC1485_GetRequiredLen(src, srclen, &mode) + 1; - if (reqLen > dstlen) { - PORT_SetError(SEC_ERROR_OUTPUT_LEN); - return SECFailure; - } - - if (mode == minimalEscapeAndQuote) - *dst++ = C_DOUBLE_QUOTE; - for (i = 0; i < srclen; i++) { - char c = src[i]; - if (NEEDS_HEX_ESCAPE(c)) { - *dst++ = C_BACKSLASH; - *dst++ = hexChars[ (c >> 4) & 0x0f ]; - *dst++ = hexChars[ c & 0x0f ]; - } else { - if (NEEDS_ESCAPE(c) || (SPECIAL_CHAR(c) && mode == fullEscape)) { - *dst++ = C_BACKSLASH; - } - *dst++ = c; - } - } - if (mode == minimalEscapeAndQuote) - *dst++ = C_DOUBLE_QUOTE; - *dst++ = 0; - if (pEQMode) - *pEQMode = mode; - return SECSuccess; -} - -SECStatus -CERT_RFC1485_EscapeAndQuote(char *dst, int dstlen, char *src, int srclen) -{ - EQMode mode = minimalEscapeAndQuote; - return escapeAndQuote(dst, dstlen, src, srclen, &mode); -} - - -/* convert an OID to dotted-decimal representation */ -/* Returns a string that must be freed with PR_smprintf_free(), */ -char * -CERT_GetOidString(const SECItem *oid) -{ - PRUint8 *stop; /* points to first byte after OID string */ - PRUint8 *first; /* byte of an OID component integer */ - PRUint8 *last; /* byte of an OID component integer */ - char *rvString = NULL; - char *prefix = NULL; - -#define MAX_OID_LEN 1024 /* bytes */ - - if (oid->len > MAX_OID_LEN) { - PORT_SetError(SEC_ERROR_INPUT_LEN); - return NULL; - } - - /* first will point to the next sequence of bytes to decode */ - first = (PRUint8 *)oid->data; - /* stop points to one past the legitimate data */ - stop = &first[ oid->len ]; - - /* - * Check for our pseudo-encoded single-digit OIDs - */ - if ((*first == 0x80) && (2 == oid->len)) { - /* Funky encoding. The second byte is the number */ - rvString = PR_smprintf("%lu", (PRUint32)first[1]); - if (!rvString) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - return rvString; - } - - for (; first < stop; first = last + 1) { - unsigned int bytesBeforeLast; - - for (last = first; last < stop; last++) { - if (0 == (*last & 0x80)) { - break; - } - } - bytesBeforeLast = (unsigned int)(last - first); - if (bytesBeforeLast <= 3U) { /* 0-28 bit number */ - PRUint32 n = 0; - PRUint32 c; - -#define CGET(i, m) \ - c = last[-i] & m; \ - n |= c << (7 * i) - -#define CASE(i, m) \ - case i: \ - CGET(i, m); \ - if (!n) goto unsupported \ - /* fall-through */ - - switch (bytesBeforeLast) { - CASE(3, 0x7f); - CASE(2, 0x7f); - CASE(1, 0x7f); - case 0: n |= last[0] & 0x7f; - break; - } - if (last[0] & 0x80) - goto unsupported; - - if (!rvString) { - /* This is the first number.. decompose it */ - PRUint32 one = PR_MIN(n/40, 2); /* never > 2 */ - PRUint32 two = n - (one * 40); - - rvString = PR_smprintf("OID.%lu.%lu", one, two); - } else { - prefix = rvString; - rvString = PR_smprintf("%s.%lu", prefix, n); - } - } else if (bytesBeforeLast <= 9U) { /* 29-64 bit number */ - PRUint64 n = 0; - PRUint64 c; - - switch (bytesBeforeLast) { - CASE(9, 0x01); - CASE(8, 0x7f); - CASE(7, 0x7f); - CASE(6, 0x7f); - CASE(5, 0x7f); - CASE(4, 0x7f); - CGET(3, 0x7f); - CGET(2, 0x7f); - CGET(1, 0x7f); - CGET(0, 0x7f); - break; - } - if (last[0] & 0x80) - goto unsupported; - - if (!rvString) { - /* This is the first number.. decompose it */ - PRUint64 one = PR_MIN(n/40, 2); /* never > 2 */ - PRUint64 two = n - (one * 40); - - rvString = PR_smprintf("OID.%llu.%llu", one, two); - } else { - prefix = rvString; - rvString = PR_smprintf("%s.%llu", prefix, n); - } - } else { - /* More than a 64-bit number, or not minimal encoding. */ -unsupported: - if (!rvString) - rvString = PR_smprintf("OID.UNSUPPORTED"); - else { - prefix = rvString; - rvString = PR_smprintf("%s.UNSUPPORTED", prefix); - } - } - - if (prefix) { - PR_smprintf_free(prefix); - prefix = NULL; - } - if (!rvString) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - break; - } - } - return rvString; -} - -/* convert DER-encoded hex to a string */ -static SECItem * -get_hex_string(SECItem *data) -{ - SECItem *rv; - unsigned int i, j; - static const char hex[] = { "0123456789ABCDEF" }; - - /* '#' + 2 chars per octet + terminator */ - rv = SECITEM_AllocItem(NULL, NULL, data->len*2 + 2); - if (!rv) { - return NULL; - } - rv->data[0] = '#'; - rv->len = 1 + 2 * data->len; - for (i=0; i<data->len; i++) { - j = data->data[i]; - rv->data[2*i+1] = hex[j >> 4]; - rv->data[2*i+2] = hex[j & 15]; - } - rv->data[rv->len] = 0; - return rv; -} - -/* For compliance with RFC 2253, RFC 3280 and RFC 4630, we choose to - * use the NAME=STRING form, rather than the OID.N.N=#hexXXXX form, - * when both of these conditions are met: - * 1) The attribute name OID (kind) has a known name string that is - * defined in one of those RFCs, or in RFCs that they cite, AND - * 2) The attribute's value encoding is RFC compliant for the kind - * (e.g., the value's encoding tag is correct for the kind, and - * the value's length is in the range allowed for the kind, and - * the value's contents are appropriate for the encoding tag). - * Otherwise, we use the OID.N.N=#hexXXXX form. - * - * If the caller prefers maximum human readability to RFC compliance, - * then - * - We print the kind in NAME= string form if we know the name - * string for the attribute type OID, regardless of whether the - * value is correctly encoded or not. else we use the OID.N.N= form. - * - We use the non-hex STRING form for the attribute value if the - * value can be represented in such a form. Otherwise, we use - * the hex string form. - * This implies that, for maximum human readability, in addition to - * the two forms allowed by the RFC, we allow two other forms of output: - * - the OID.N.N=STRING form, and - * - the NAME=#hexXXXX form - * When the caller prefers maximum human readability, we do not allow - * the value of any attribute to exceed the length allowed by the RFC. - * If the attribute value exceeds the allowed length, we truncate it to - * the allowed length and append "...". - * Also in this case, we arbitrarily impose a limit on the length of the - * entire AVA encoding, regardless of the form, of 384 bytes per AVA. - * This limit includes the trailing NULL character. If the encoded - * AVA length exceeds that limit, this function reports failure to encode - * the AVA. - * - * An ASCII representation of an AVA is said to be "invertible" if - * conversion back to DER reproduces the original DER encoding exactly. - * The RFC 2253 rules do not ensure that all ASCII AVAs derived according - * to its rules are invertible. That is because the RFCs allow some - * attribute values to be encoded in any of a number of encodings, - * and the encoding type information is lost in the non-hex STRING form. - * This is particularly true of attributes of type DirectoryString. - * The encoding type information is always preserved in the hex string - * form, because the hex includes the entire DER encoding of the value. - * - * So, when the caller perfers maximum invertibility, we apply the - * RFC compliance rules stated above, and add a third required - * condition on the use of the NAME=STRING form. - * 3) The attribute's kind is not is allowed to be encoded in any of - * several different encodings, such as DirectoryStrings. - * - * The chief difference between CERT_N2A_STRICT and CERT_N2A_INVERTIBLE - * is that the latter forces DirectoryStrings to be hex encoded. - * - * As a simplification, we assume the value is correctly encoded for - * its encoding type. That is, we do not test that all the characters - * in a string encoded type are allowed by that type. We assume it. - */ -static SECStatus -AppendAVA(stringBuf *bufp, CERTAVA *ava, CertStrictnessLevel strict) -{ -#define TMPBUF_LEN 384 - const NameToKind *pn2k = name2kinds; - SECItem *avaValue = NULL; - char *unknownTag = NULL; - char *encodedAVA = NULL; - PRBool useHex = PR_FALSE; /* use =#hexXXXX form */ - PRBool truncateName = PR_FALSE; - PRBool truncateValue = PR_FALSE; - SECOidTag endKind; - SECStatus rv; - unsigned int len; - unsigned int nameLen, valueLen; - unsigned int maxName, maxValue; - EQMode mode = minimalEscapeAndQuote; - NameToKind n2k = { NULL, 32767, SEC_OID_UNKNOWN, SEC_ASN1_DS }; - char tmpBuf[TMPBUF_LEN]; - -#define tagName n2k.name /* non-NULL means use NAME= form */ -#define maxBytes n2k.maxLen -#define tag n2k.kind -#define vt n2k.valueType - - /* READABLE mode recognizes more names from the name2kinds table - * than do STRICT or INVERTIBLE modes. This assignment chooses the - * point in the table where the attribute type name scanning stops. - */ - endKind = (strict == CERT_N2A_READABLE) ? SEC_OID_UNKNOWN - : SEC_OID_AVA_POSTAL_ADDRESS; - tag = CERT_GetAVATag(ava); - while (pn2k->kind != tag && pn2k->kind != endKind) { - ++pn2k; - } - - if (pn2k->kind != endKind ) { - n2k = *pn2k; - } else if (strict != CERT_N2A_READABLE) { - useHex = PR_TRUE; - } - /* For invertable form, force Directory Strings to use hex form. */ - if (strict == CERT_N2A_INVERTIBLE && vt == SEC_ASN1_DS) { - tagName = NULL; /* must use OID.N form */ - useHex = PR_TRUE; /* must use hex string */ - } - if (!useHex) { - avaValue = CERT_DecodeAVAValue(&ava->value); - if (!avaValue) { - useHex = PR_TRUE; - if (strict != CERT_N2A_READABLE) { - tagName = NULL; /* must use OID.N form */ - } - } - } - if (!tagName) { - /* handle unknown attribute types per RFC 2253 */ - tagName = unknownTag = CERT_GetOidString(&ava->type); - if (!tagName) { - if (avaValue) - SECITEM_FreeItem(avaValue, PR_TRUE); - return SECFailure; - } - } - if (useHex) { - avaValue = get_hex_string(&ava->value); - if (!avaValue) { - if (unknownTag) - PR_smprintf_free(unknownTag); - return SECFailure; - } - } - - nameLen = strlen(tagName); - valueLen = (useHex ? avaValue->len : - cert_RFC1485_GetRequiredLen((char *)avaValue->data, avaValue->len, - &mode)); - len = nameLen + valueLen + 2; /* Add 2 for '=' and trailing NUL */ - - maxName = nameLen; - maxValue = valueLen; - if (len <= sizeof(tmpBuf)) { - encodedAVA = tmpBuf; - } else if (strict != CERT_N2A_READABLE) { - encodedAVA = PORT_Alloc(len); - if (!encodedAVA) { - SECITEM_FreeItem(avaValue, PR_TRUE); - if (unknownTag) - PR_smprintf_free(unknownTag); - return SECFailure; - } - } else { - /* Must make output fit in tmpbuf */ - unsigned int fair = (sizeof tmpBuf)/2 - 1; /* for = and \0 */ - - if (nameLen < fair) { - /* just truncate the value */ - maxValue = (sizeof tmpBuf) - (nameLen + 6); /* for "=...\0", - and possibly '"' */ - } else if (valueLen < fair) { - /* just truncate the name */ - maxName = (sizeof tmpBuf) - (valueLen + 5); /* for "=...\0" */ - } else { - /* truncate both */ - maxName = maxValue = fair - 3; /* for "..." */ - } - if (nameLen > maxName) { - PORT_Assert(unknownTag && unknownTag == tagName); - truncateName = PR_TRUE; - nameLen = maxName; - } - encodedAVA = tmpBuf; - } - - memcpy(encodedAVA, tagName, nameLen); - if (truncateName) { - /* If tag name is too long, we know it is an OID form that was - * allocated from the heap, so we can modify it in place - */ - encodedAVA[nameLen-1] = '.'; - encodedAVA[nameLen-2] = '.'; - encodedAVA[nameLen-3] = '.'; - } - encodedAVA[nameLen++] = '='; - if (unknownTag) - PR_smprintf_free(unknownTag); - - if (strict == CERT_N2A_READABLE && maxValue > maxBytes) - maxValue = maxBytes; - if (valueLen > maxValue) { - valueLen = maxValue; - truncateValue = PR_TRUE; - } - /* escape and quote as necessary - don't quote hex strings */ - if (useHex) { - char * end = encodedAVA + nameLen + valueLen; - memcpy(encodedAVA + nameLen, (char *)avaValue->data, valueLen); - end[0] = '\0'; - if (truncateValue) { - end[-1] = '.'; - end[-2] = '.'; - end[-3] = '.'; - } - rv = SECSuccess; - } else if (!truncateValue) { - rv = escapeAndQuote(encodedAVA + nameLen, len - nameLen, - (char *)avaValue->data, avaValue->len, &mode); - } else { - /* must truncate the escaped and quoted value */ - char bigTmpBuf[TMPBUF_LEN * 3 + 3]; - rv = escapeAndQuote(bigTmpBuf, sizeof bigTmpBuf, - (char *)avaValue->data, valueLen, &mode); - - bigTmpBuf[valueLen--] = '\0'; /* hard stop here */ - /* See if we're in the middle of a multi-byte UTF8 character */ - while (((bigTmpBuf[valueLen] & 0xc0) == 0x80) && valueLen > 0) { - bigTmpBuf[valueLen--] = '\0'; - } - /* add ellipsis to signify truncation. */ - bigTmpBuf[++valueLen] = '.'; - bigTmpBuf[++valueLen] = '.'; - bigTmpBuf[++valueLen] = '.'; - if (bigTmpBuf[0] == '"') - bigTmpBuf[++valueLen] = '"'; - bigTmpBuf[++valueLen] = '\0'; - PORT_Assert(nameLen + valueLen <= (sizeof tmpBuf) - 1); - memcpy(encodedAVA + nameLen, bigTmpBuf, valueLen+1); - } - - SECITEM_FreeItem(avaValue, PR_TRUE); - if (rv == SECSuccess) - rv = AppendStr(bufp, encodedAVA); - if (encodedAVA != tmpBuf) - PORT_Free(encodedAVA); - return rv; -} - -#undef tagName -#undef maxBytes -#undef tag -#undef vt - -char * -CERT_NameToAsciiInvertible(CERTName *name, CertStrictnessLevel strict) -{ - CERTRDN** rdns; - CERTRDN** lastRdn; - CERTRDN** rdn; - PRBool first = PR_TRUE; - stringBuf strBuf = { NULL, 0, 0 }; - - rdns = name->rdns; - if (rdns == NULL) { - return NULL; - } - - /* find last RDN */ - lastRdn = rdns; - while (*lastRdn) lastRdn++; - lastRdn--; - - /* - * Loop over name contents in _reverse_ RDN order appending to string - */ - for (rdn = lastRdn; rdn >= rdns; rdn--) { - CERTAVA** avas = (*rdn)->avas; - CERTAVA* ava; - PRBool newRDN = PR_TRUE; - - /* - * XXX Do we need to traverse the AVAs in reverse order, too? - */ - while (avas && (ava = *avas++) != NULL) { - SECStatus rv; - /* Put in comma or plus separator */ - if (!first) { - /* Use of spaces is deprecated in RFC 2253. */ - rv = AppendStr(&strBuf, newRDN ? "," : "+"); - if (rv) goto loser; - } else { - first = PR_FALSE; - } - - /* Add in tag type plus value into strBuf */ - rv = AppendAVA(&strBuf, ava, strict); - if (rv) goto loser; - newRDN = PR_FALSE; - } - } - return strBuf.buffer; -loser: - if (strBuf.buffer) { - PORT_Free(strBuf.buffer); - } - return NULL; -} - -char * -CERT_NameToAscii(CERTName *name) -{ - return CERT_NameToAsciiInvertible(name, CERT_N2A_READABLE); -} - -/* - * Return the string representation of a DER encoded distinguished name - * "dername" - The DER encoded name to convert - */ -char * -CERT_DerNameToAscii(SECItem *dername) -{ - int rv; - PRArenaPool *arena = NULL; - CERTName name; - char *retstr = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - - if ( arena == NULL) { - goto loser; - } - - rv = SEC_QuickDERDecodeItem(arena, &name, CERT_NameTemplate, dername); - - if ( rv != SECSuccess ) { - goto loser; - } - - retstr = CERT_NameToAscii(&name); - -loser: - if ( arena != NULL ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(retstr); -} - -static char * -avaToString(PRArenaPool *arena, CERTAVA *ava) -{ - char * buf = NULL; - SECItem* avaValue; - int valueLen; - - avaValue = CERT_DecodeAVAValue(&ava->value); - if(!avaValue) { - return buf; - } - valueLen = cert_RFC1485_GetRequiredLen((char *)avaValue->data, - avaValue->len, NULL) + 1; - if (arena) { - buf = (char *)PORT_ArenaZAlloc(arena, valueLen); - } else { - buf = (char *)PORT_ZAlloc(valueLen); - } - if (buf) { - SECStatus rv = escapeAndQuote(buf, valueLen, (char *)avaValue->data, - avaValue->len, NULL); - if (rv != SECSuccess) { - if (!arena) - PORT_Free(buf); - buf = NULL; - } - } - SECITEM_FreeItem(avaValue, PR_TRUE); - return buf; -} - -/* RDNs are sorted from most general to most specific. - * This code returns the FIRST one found, the most general one found. - */ -static char * -CERT_GetNameElement(PRArenaPool *arena, CERTName *name, int wantedTag) -{ - CERTRDN** rdns = name->rdns; - CERTRDN* rdn; - CERTAVA* ava = NULL; - - while (rdns && (rdn = *rdns++) != 0) { - CERTAVA** avas = rdn->avas; - while (avas && (ava = *avas++) != 0) { - int tag = CERT_GetAVATag(ava); - if ( tag == wantedTag ) { - avas = NULL; - rdns = NULL; /* break out of all loops */ - } - } - } - return ava ? avaToString(arena, ava) : NULL; -} - -/* RDNs are sorted from most general to most specific. - * This code returns the LAST one found, the most specific one found. - * This is particularly appropriate for Common Name. See RFC 2818. - */ -static char * -CERT_GetLastNameElement(PRArenaPool *arena, CERTName *name, int wantedTag) -{ - CERTRDN** rdns = name->rdns; - CERTRDN* rdn; - CERTAVA* lastAva = NULL; - - while (rdns && (rdn = *rdns++) != 0) { - CERTAVA** avas = rdn->avas; - CERTAVA* ava; - while (avas && (ava = *avas++) != 0) { - int tag = CERT_GetAVATag(ava); - if ( tag == wantedTag ) { - lastAva = ava; - } - } - } - return lastAva ? avaToString(arena, lastAva) : NULL; -} - -char * -CERT_GetCertificateEmailAddress(CERTCertificate *cert) -{ - char *rawEmailAddr = NULL; - SECItem subAltName; - SECStatus rv; - CERTGeneralName *nameList = NULL; - CERTGeneralName *current; - PRArenaPool *arena = NULL; - int i; - - subAltName.data = NULL; - - rawEmailAddr = CERT_GetNameElement(cert->arena, &(cert->subject), - SEC_OID_PKCS9_EMAIL_ADDRESS); - if ( rawEmailAddr == NULL ) { - rawEmailAddr = CERT_GetNameElement(cert->arena, &(cert->subject), - SEC_OID_RFC1274_MAIL); - } - if ( rawEmailAddr == NULL) { - - rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME, - &subAltName); - if (rv != SECSuccess) { - goto finish; - } - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (!arena) { - goto finish; - } - nameList = current = CERT_DecodeAltNameExtension(arena, &subAltName); - if (!nameList ) { - goto finish; - } - if (nameList != NULL) { - do { - if (current->type == certDirectoryName) { - rawEmailAddr = CERT_GetNameElement(cert->arena, - &(current->name.directoryName), - SEC_OID_PKCS9_EMAIL_ADDRESS); - if ( rawEmailAddr == NULL ) { - rawEmailAddr = CERT_GetNameElement(cert->arena, - &(current->name.directoryName), SEC_OID_RFC1274_MAIL); - } - } else if (current->type == certRFC822Name) { - rawEmailAddr = (char*)PORT_ArenaZAlloc(cert->arena, - current->name.other.len + 1); - if (!rawEmailAddr) { - goto finish; - } - PORT_Memcpy(rawEmailAddr, current->name.other.data, - current->name.other.len); - rawEmailAddr[current->name.other.len] = '\0'; - } - if (rawEmailAddr) { - break; - } - current = CERT_GetNextGeneralName(current); - } while (current != nameList); - } - } - if (rawEmailAddr) { - for (i = 0; i <= (int) PORT_Strlen(rawEmailAddr); i++) { - rawEmailAddr[i] = tolower(rawEmailAddr[i]); - } - } - -finish: - - /* Don't free nameList, it's part of the arena. */ - - if (arena) { - PORT_FreeArena(arena, PR_FALSE); - } - - if ( subAltName.data ) { - SECITEM_FreeItem(&subAltName, PR_FALSE); - } - - return(rawEmailAddr); -} - -static char * -appendStringToBuf(char *dest, char *src, PRUint32 *pRemaining) -{ - PRUint32 len; - if (dest && src && src[0] && *pRemaining > (len = PL_strlen(src))) { - PRUint32 i; - for (i = 0; i < len; ++i) - dest[i] = tolower(src[i]); - dest[len] = 0; - dest += len + 1; - *pRemaining -= len + 1; - } - return dest; -} - -#undef NEEDS_HEX_ESCAPE -#define NEEDS_HEX_ESCAPE(c) (c < 0x20) - -static char * -appendItemToBuf(char *dest, SECItem *src, PRUint32 *pRemaining) -{ - if (dest && src && src->data && src->len && src->data[0]) { - PRUint32 len = src->len; - PRUint32 i; - PRUint32 reqLen = len + 1; - /* are there any embedded control characters ? */ - for (i = 0; i < len; i++) { - if (NEEDS_HEX_ESCAPE(src->data[i])) - reqLen += 2; - } - if (*pRemaining > reqLen) { - for (i = 0; i < len; ++i) { - PRUint8 c = src->data[i]; - if (NEEDS_HEX_ESCAPE(c)) { - *dest++ = C_BACKSLASH; - *dest++ = hexChars[ (c >> 4) & 0x0f ]; - *dest++ = hexChars[ c & 0x0f ]; - } else { - *dest++ = tolower(c); - } - } - *dest++ = '\0'; - *pRemaining -= reqLen; - } - } - return dest; -} - -/* Returns a pointer to an environment-like string, a series of -** null-terminated strings, terminated by a zero-length string. -** This function is intended to be internal to NSS. -*/ -char * -cert_GetCertificateEmailAddresses(CERTCertificate *cert) -{ - char * rawEmailAddr = NULL; - char * addrBuf = NULL; - char * pBuf = NULL; - PRArenaPool * tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - PRUint32 maxLen = 0; - PRInt32 finalLen = 0; - SECStatus rv; - SECItem subAltName; - - if (!tmpArena) - return addrBuf; - - subAltName.data = NULL; - maxLen = cert->derCert.len; - PORT_Assert(maxLen); - if (!maxLen) - maxLen = 2000; /* a guess, should never happen */ - - pBuf = addrBuf = (char *)PORT_ArenaZAlloc(tmpArena, maxLen + 1); - if (!addrBuf) - goto loser; - - rawEmailAddr = CERT_GetNameElement(tmpArena, &cert->subject, - SEC_OID_PKCS9_EMAIL_ADDRESS); - pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen); - - rawEmailAddr = CERT_GetNameElement(tmpArena, &cert->subject, - SEC_OID_RFC1274_MAIL); - pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen); - - rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME, - &subAltName); - if (rv == SECSuccess && subAltName.data) { - CERTGeneralName *nameList = NULL; - - if (!!(nameList = CERT_DecodeAltNameExtension(tmpArena, &subAltName))) { - CERTGeneralName *current = nameList; - do { - if (current->type == certDirectoryName) { - rawEmailAddr = CERT_GetNameElement(tmpArena, - ¤t->name.directoryName, - SEC_OID_PKCS9_EMAIL_ADDRESS); - pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen); - - rawEmailAddr = CERT_GetNameElement(tmpArena, - ¤t->name.directoryName, - SEC_OID_RFC1274_MAIL); - pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen); - } else if (current->type == certRFC822Name) { - pBuf = appendItemToBuf(pBuf, ¤t->name.other, &maxLen); - } - current = CERT_GetNextGeneralName(current); - } while (current != nameList); - } - SECITEM_FreeItem(&subAltName, PR_FALSE); - /* Don't free nameList, it's part of the tmpArena. */ - } - /* now copy superstring to cert's arena */ - finalLen = (pBuf - addrBuf) + 1; - pBuf = NULL; - if (finalLen > 1) { - pBuf = PORT_ArenaAlloc(cert->arena, finalLen); - if (pBuf) { - PORT_Memcpy(pBuf, addrBuf, finalLen); - } - } -loser: - if (tmpArena) - PORT_FreeArena(tmpArena, PR_FALSE); - - return pBuf; -} - -/* returns pointer to storage in cert's arena. Storage remains valid -** as long as cert's reference count doesn't go to zero. -** Caller should strdup or otherwise copy. -*/ -const char * /* const so caller won't muck with it. */ -CERT_GetFirstEmailAddress(CERTCertificate * cert) -{ - if (cert && cert->emailAddr && cert->emailAddr[0]) - return (const char *)cert->emailAddr; - return NULL; -} - -/* returns pointer to storage in cert's arena. Storage remains valid -** as long as cert's reference count doesn't go to zero. -** Caller should strdup or otherwise copy. -*/ -const char * /* const so caller won't muck with it. */ -CERT_GetNextEmailAddress(CERTCertificate * cert, const char * prev) -{ - if (cert && prev && prev[0]) { - PRUint32 len = PL_strlen(prev); - prev += len + 1; - if (prev && prev[0]) - return prev; - } - return NULL; -} - -/* This is seriously bogus, now that certs store their email addresses in -** subject Alternative Name extensions. -** Returns a string allocated by PORT_StrDup, which the caller must free. -*/ -char * -CERT_GetCertEmailAddress(CERTName *name) -{ - char *rawEmailAddr; - char *emailAddr; - - - rawEmailAddr = CERT_GetNameElement(NULL, name, SEC_OID_PKCS9_EMAIL_ADDRESS); - if ( rawEmailAddr == NULL ) { - rawEmailAddr = CERT_GetNameElement(NULL, name, SEC_OID_RFC1274_MAIL); - } - emailAddr = CERT_FixupEmailAddr(rawEmailAddr); - if ( rawEmailAddr ) { - PORT_Free(rawEmailAddr); - } - return(emailAddr); -} - -/* The return value must be freed with PORT_Free. */ -char * -CERT_GetCommonName(CERTName *name) -{ - return(CERT_GetLastNameElement(NULL, name, SEC_OID_AVA_COMMON_NAME)); -} - -char * -CERT_GetCountryName(CERTName *name) -{ - return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_COUNTRY_NAME)); -} - -char * -CERT_GetLocalityName(CERTName *name) -{ - return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_LOCALITY)); -} - -char * -CERT_GetStateName(CERTName *name) -{ - return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_STATE_OR_PROVINCE)); -} - -char * -CERT_GetOrgName(CERTName *name) -{ - return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_ORGANIZATION_NAME)); -} - -char * -CERT_GetDomainComponentName(CERTName *name) -{ - return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_DC)); -} - -char * -CERT_GetOrgUnitName(CERTName *name) -{ - return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME)); -} - -char * -CERT_GetDnQualifier(CERTName *name) -{ - return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_DN_QUALIFIER)); -} - -char * -CERT_GetCertUid(CERTName *name) -{ - return(CERT_GetNameElement(NULL, name, SEC_OID_RFC1274_UID)); -} - diff --git a/security/nss/lib/certdb/cert.h b/security/nss/lib/certdb/cert.h deleted file mode 100644 index fb324a09d..000000000 --- a/security/nss/lib/certdb/cert.h +++ /dev/null @@ -1,1650 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * cert.h - public data structures and prototypes for the certificate library - * - * $Id$ - */ - -#ifndef _CERT_H_ -#define _CERT_H_ - -#include "utilrename.h" -#include "plarena.h" -#include "plhash.h" -#include "prlong.h" -#include "prlog.h" - -#include "seccomon.h" -#include "secdert.h" -#include "secoidt.h" -#include "keyt.h" -#include "certt.h" - -SEC_BEGIN_PROTOS - -/**************************************************************************** - * - * RFC1485 ascii to/from X.? RelativeDistinguishedName (aka CERTName) - * - ****************************************************************************/ - -/* -** Convert an ascii RFC1485 encoded name into its CERTName equivalent. -*/ -extern CERTName *CERT_AsciiToName(const char *string); - -/* -** Convert an CERTName into its RFC1485 encoded equivalent. -** Returns a string that must be freed with PORT_Free(). -** This version produces a string for maximum human readability, -** not for strict RFC compliance. -*/ -extern char *CERT_NameToAscii(CERTName *name); - -/* -** Convert an CERTName into its RFC1485 encoded equivalent. -** Returns a string that must be freed with PORT_Free(). -** Caller chooses encoding rules. -*/ -extern char *CERT_NameToAsciiInvertible(CERTName *name, - CertStrictnessLevel strict); - -extern CERTAVA *CERT_CopyAVA(PLArenaPool *arena, CERTAVA *src); - -/* convert an OID to dotted-decimal representation */ -/* Returns a string that must be freed with PR_smprintf_free(). */ -extern char * CERT_GetOidString(const SECItem *oid); - -/* -** Examine an AVA and return the tag that refers to it. The AVA tags are -** defined as SEC_OID_AVA*. -*/ -extern SECOidTag CERT_GetAVATag(CERTAVA *ava); - -/* -** Compare two AVA's, returning the difference between them. -*/ -extern SECComparison CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b); - -/* -** Create an RDN (relative-distinguished-name). The argument list is a -** NULL terminated list of AVA's. -*/ -extern CERTRDN *CERT_CreateRDN(PLArenaPool *arena, CERTAVA *avas, ...); - -/* -** Make a copy of "src" storing it in "dest". -*/ -extern SECStatus CERT_CopyRDN(PLArenaPool *arena, CERTRDN *dest, CERTRDN *src); - -/* -** Destory an RDN object. -** "rdn" the RDN to destroy -** "freeit" if PR_TRUE then free the object as well as its sub-objects -*/ -extern void CERT_DestroyRDN(CERTRDN *rdn, PRBool freeit); - -/* -** Add an AVA to an RDN. -** "rdn" the RDN to add to -** "ava" the AVA to add -*/ -extern SECStatus CERT_AddAVA(PLArenaPool *arena, CERTRDN *rdn, CERTAVA *ava); - -/* -** Compare two RDN's, returning the difference between them. -*/ -extern SECComparison CERT_CompareRDN(const CERTRDN *a, const CERTRDN *b); - -/* -** Create an X.500 style name using a NULL terminated list of RDN's. -*/ -extern CERTName *CERT_CreateName(CERTRDN *rdn, ...); - -/* -** Make a copy of "src" storing it in "dest". Memory is allocated in -** "dest" for each of the appropriate sub objects. Memory is not freed in -** "dest" before allocation is done (use CERT_DestroyName(dest, PR_FALSE) to -** do that). -*/ -extern SECStatus CERT_CopyName(PLArenaPool *arena, CERTName *dest, CERTName *src); - -/* -** Destroy a Name object. -** "name" the CERTName to destroy -** "freeit" if PR_TRUE then free the object as well as its sub-objects -*/ -extern void CERT_DestroyName(CERTName *name); - -/* -** Add an RDN to a name. -** "name" the name to add the RDN to -** "rdn" the RDN to add to name -*/ -extern SECStatus CERT_AddRDN(CERTName *name, CERTRDN *rdn); - -/* -** Compare two names, returning the difference between them. -*/ -extern SECComparison CERT_CompareName(const CERTName *a, const CERTName *b); - -/* -** Convert a CERTName into something readable -*/ -extern char *CERT_FormatName (CERTName *name); - -/* -** Convert a der-encoded integer to a hex printable string form. -** Perhaps this should be a SEC function but it's only used for certs. -*/ -extern char *CERT_Hexify (SECItem *i, int do_colon); - -/* -** Converts DER string (with explicit length) into zString, if destination -** buffer is big enough to receive it. Does quoting and/or escaping as -** specified in RFC 1485. Input string must be single or multi-byte DER -** character set, (ASCII, UTF8, or ISO 8851-x) not a wide character set. -** Returns SECSuccess or SECFailure with error code set. If output buffer -** is too small, sets error code SEC_ERROR_OUTPUT_LEN. -*/ -extern SECStatus -CERT_RFC1485_EscapeAndQuote(char *dst, int dstlen, char *src, int srclen); - -/****************************************************************************** - * - * Certificate handling operations - * - *****************************************************************************/ - -/* -** Create a new validity object given two unix time values. -** "notBefore" the time before which the validity is not valid -** "notAfter" the time after which the validity is not valid -*/ -extern CERTValidity *CERT_CreateValidity(PRTime notBefore, PRTime notAfter); - -/* -** Destroy a validity object. -** "v" the validity to destroy -** "freeit" if PR_TRUE then free the object as well as its sub-objects -*/ -extern void CERT_DestroyValidity(CERTValidity *v); - -/* -** Copy the "src" object to "dest". Memory is allocated in "dest" for -** each of the appropriate sub-objects. Memory in "dest" is not freed -** before memory is allocated (use CERT_DestroyValidity(v, PR_FALSE) to do -** that). -*/ -extern SECStatus CERT_CopyValidity - (PLArenaPool *arena, CERTValidity *dest, CERTValidity *src); - -/* -** The cert lib considers a cert or CRL valid if the "notBefore" time is -** in the not-too-distant future, e.g. within the next 24 hours. This -** prevents freshly issued certificates from being considered invalid -** because the local system's time zone is incorrectly set. -** The amount of "pending slop time" is adjustable by the application. -** Units of SlopTime are seconds. Default is 86400 (24 hours). -** Negative SlopTime values are not allowed. -*/ -PRInt32 CERT_GetSlopTime(void); - -SECStatus CERT_SetSlopTime(PRInt32 slop); - -/* -** Create a new certificate object. The result must be wrapped with an -** CERTSignedData to create a signed certificate. -** "serialNumber" the serial number -** "issuer" the name of the certificate issuer -** "validity" the validity period of the certificate -** "req" the certificate request that prompted the certificate issuance -*/ -extern CERTCertificate * -CERT_CreateCertificate (unsigned long serialNumber, CERTName *issuer, - CERTValidity *validity, CERTCertificateRequest *req); - -/* -** Destroy a certificate object -** "cert" the certificate to destroy -** NOTE: certificate's are reference counted. This call decrements the -** reference count, and if the result is zero, then the object is destroyed -** and optionally freed. -*/ -extern void CERT_DestroyCertificate(CERTCertificate *cert); - -/* -** Make a shallow copy of a certificate "c". Just increments the -** reference count on "c". -*/ -extern CERTCertificate *CERT_DupCertificate(CERTCertificate *c); - -/* -** Create a new certificate request. This result must be wrapped with an -** CERTSignedData to create a signed certificate request. -** "name" the subject name (who the certificate request is from) -** "spki" describes/defines the public key the certificate is for -** "attributes" if non-zero, some optional attribute data -*/ -extern CERTCertificateRequest * -CERT_CreateCertificateRequest (CERTName *name, CERTSubjectPublicKeyInfo *spki, - SECItem **attributes); - -/* -** Destroy a certificate-request object -** "r" the certificate-request to destroy -** "freeit" if PR_TRUE then free the object as well as its sub-objects -*/ -extern void CERT_DestroyCertificateRequest(CERTCertificateRequest *r); - -/* -** Start adding extensions to a certificate request. -*/ -void * -CERT_StartCertificateRequestAttributes(CERTCertificateRequest *req); - -/* -** Reformat the certificate extension list into a CertificateRequest -** attribute list. -*/ -SECStatus -CERT_FinishCertificateRequestAttributes(CERTCertificateRequest *req); - -/* -** Extract the Extension Requests from a DER CertRequest attribute list. -*/ -SECStatus -CERT_GetCertificateRequestExtensions(CERTCertificateRequest *req, - CERTCertExtension ***exts); - -/* -** Extract a public key object from a certificate -*/ -extern SECKEYPublicKey *CERT_ExtractPublicKey(CERTCertificate *cert); - -/* -** Retrieve the Key Type associated with the cert we're dealing with -*/ - -extern KeyType CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki); - -/* -** Initialize the certificate database. This is called to create -** the initial list of certificates in the database. -*/ -extern SECStatus CERT_InitCertDB(CERTCertDBHandle *handle); - -extern int CERT_GetDBContentVersion(CERTCertDBHandle *handle); - -/* -** Default certificate database routines -*/ -extern void CERT_SetDefaultCertDB(CERTCertDBHandle *handle); - -extern CERTCertDBHandle *CERT_GetDefaultCertDB(void); - -extern CERTCertList *CERT_GetCertChainFromCert(CERTCertificate *cert, - PRTime time, - SECCertUsage usage); -extern CERTCertificate * -CERT_NewTempCertificate (CERTCertDBHandle *handle, SECItem *derCert, - char *nickname, PRBool isperm, PRBool copyDER); - - -/****************************************************************************** - * - * X.500 Name handling operations - * - *****************************************************************************/ - -/* -** Create an AVA (attribute-value-assertion) -** "arena" the memory arena to alloc from -** "kind" is one of SEC_OID_AVA_* -** "valueType" is one of DER_PRINTABLE_STRING, DER_IA5_STRING, or -** DER_T61_STRING -** "value" is the null terminated string containing the value -*/ -extern CERTAVA *CERT_CreateAVA - (PLArenaPool *arena, SECOidTag kind, int valueType, char *value); - -/* -** Extract the Distinguished Name from a DER encoded certificate -** "derCert" is the DER encoded certificate -** "derName" is the SECItem that the name is returned in -*/ -extern SECStatus CERT_NameFromDERCert(SECItem *derCert, SECItem *derName); - -/* -** Extract the Issuers Distinguished Name from a DER encoded certificate -** "derCert" is the DER encoded certificate -** "derName" is the SECItem that the name is returned in -*/ -extern SECStatus CERT_IssuerNameFromDERCert(SECItem *derCert, - SECItem *derName); - -extern SECItem * -CERT_EncodeGeneralName(CERTGeneralName *genName, SECItem *dest, - PLArenaPool *arena); - -extern CERTGeneralName * -CERT_DecodeGeneralName(PLArenaPool *reqArena, SECItem *encodedName, - CERTGeneralName *genName); - - - -/* -** Generate a database search key for a certificate, based on the -** issuer and serial number. -** "arena" the memory arena to alloc from -** "derCert" the DER encoded certificate -** "key" the returned key -*/ -extern SECStatus CERT_KeyFromDERCert(PLArenaPool *reqArena, SECItem *derCert, - SECItem *key); - -extern SECStatus CERT_KeyFromIssuerAndSN(PLArenaPool *arena, SECItem *issuer, - SECItem *sn, SECItem *key); - -extern SECStatus CERT_SerialNumberFromDERCert(SECItem *derCert, - SECItem *derName); - - -/* -** Generate a database search key for a crl, based on the -** issuer. -** "arena" the memory arena to alloc from -** "derCrl" the DER encoded crl -** "key" the returned key -*/ -extern SECStatus CERT_KeyFromDERCrl(PLArenaPool *arena, SECItem *derCrl, SECItem *key); - -/* -** Open the certificate database. Use callback to get name of database. -*/ -extern SECStatus CERT_OpenCertDB(CERTCertDBHandle *handle, PRBool readOnly, - CERTDBNameFunc namecb, void *cbarg); - -/* Open the certificate database. Use given filename for database. */ -extern SECStatus CERT_OpenCertDBFilename(CERTCertDBHandle *handle, - char *certdbname, PRBool readOnly); - -/* -** Open and initialize a cert database that is entirely in memory. This -** can be used when the permanent database can not be opened or created. -*/ -extern SECStatus CERT_OpenVolatileCertDB(CERTCertDBHandle *handle); - -/* -** Extract the list of host names, host name patters, IP address strings -** this cert is valid for. -** This function does NOT return nicknames. -** Type CERTCertNicknames is being used because it's a convenient -** data structure to carry a list of strings and its count. -*/ -extern CERTCertNicknames * - CERT_GetValidDNSPatternsFromCert(CERTCertificate *cert); - -/* -** Check the hostname to make sure that it matches the shexp that -** is given in the common name of the certificate. -*/ -extern SECStatus CERT_VerifyCertName(CERTCertificate *cert, const char *hostname); - -/* -** Add a domain name to the list of names that the user has explicitly -** allowed (despite cert name mismatches) for use with a server cert. -*/ -extern SECStatus CERT_AddOKDomainName(CERTCertificate *cert, const char *hostname); - -/* -** Decode a DER encoded certificate into an CERTCertificate structure -** "derSignedCert" is the DER encoded signed certificate -** "copyDER" is true if the DER should be copied, false if the -** existing copy should be referenced -** "nickname" is the nickname to use in the database. If it is NULL -** then a temporary nickname is generated. -*/ -extern CERTCertificate * -CERT_DecodeDERCertificate (SECItem *derSignedCert, PRBool copyDER, char *nickname); -/* -** Decode a DER encoded CRL into a CERTSignedCrl structure -** "derSignedCrl" is the DER encoded signed CRL. -** "type" must be SEC_CRL_TYPE. -*/ -#define SEC_CRL_TYPE 1 -#define SEC_KRL_TYPE 0 /* deprecated */ - -extern CERTSignedCrl * -CERT_DecodeDERCrl (PLArenaPool *arena, SECItem *derSignedCrl,int type); - -/* - * same as CERT_DecodeDERCrl, plus allow options to be passed in - */ - -extern CERTSignedCrl * -CERT_DecodeDERCrlWithFlags(PLArenaPool *narena, SECItem *derSignedCrl, - int type, PRInt32 options); - -/* CRL options to pass */ - -#define CRL_DECODE_DEFAULT_OPTIONS 0x00000000 - -/* when CRL_DECODE_DONT_COPY_DER is set, the DER is not copied . The - application must then keep derSignedCrl until it destroys the - CRL . Ideally, it should allocate derSignedCrl in an arena - and pass that arena in as the first argument to - CERT_DecodeDERCrlWithFlags */ - -#define CRL_DECODE_DONT_COPY_DER 0x00000001 -#define CRL_DECODE_SKIP_ENTRIES 0x00000002 -#define CRL_DECODE_KEEP_BAD_CRL 0x00000004 -#define CRL_DECODE_ADOPT_HEAP_DER 0x00000008 - -/* complete the decoding of a partially decoded CRL, ie. decode the - entries. Note that entries is an optional field in a CRL, so the - "entries" pointer in CERTCrlStr may still be NULL even after - function returns SECSuccess */ - -extern SECStatus CERT_CompleteCRLDecodeEntries(CERTSignedCrl* crl); - -/* Validate CRL then import it to the dbase. If there is already a CRL with the - * same CA in the dbase, it will be replaced if derCRL is more up to date. - * If the process successes, a CRL will be returned. Otherwise, a NULL will - * be returned. The caller should call PORT_GetError() for the exactly error - * code. - */ -extern CERTSignedCrl * -CERT_ImportCRL (CERTCertDBHandle *handle, SECItem *derCRL, char *url, - int type, void * wincx); - -extern void CERT_DestroyCrl (CERTSignedCrl *crl); - -/* this is a hint to flush the CRL cache. crlKey is the DER subject of - the issuer (CA). */ -void CERT_CRLCacheRefreshIssuer(CERTCertDBHandle* dbhandle, SECItem* crlKey); - -/* add the specified DER CRL object to the CRL cache. Doing so will allow - certificate verification functions (such as CERT_VerifyCertificate) - to automatically find and make use of this CRL object. - Once a CRL is added to the CRL cache, the application must hold on to - the object's memory, because the cache will reference it directly. The - application can only free the object after it calls CERT_UncacheCRL to - remove it from the CRL cache. -*/ -SECStatus CERT_CacheCRL(CERTCertDBHandle* dbhandle, SECItem* newcrl); - -/* remove a previously added CRL object from the CRL cache. It is OK - for the application to free the memory after a successful removal -*/ -SECStatus CERT_UncacheCRL(CERTCertDBHandle* dbhandle, SECItem* oldcrl); - -/* -** Find a certificate in the database -** "key" is the database key to look for -*/ -extern CERTCertificate *CERT_FindCertByKey(CERTCertDBHandle *handle, SECItem *key); - -/* -** Find a certificate in the database by name -** "name" is the distinguished name to look up -*/ -extern CERTCertificate * -CERT_FindCertByName (CERTCertDBHandle *handle, SECItem *name); - -/* -** Find a certificate in the database by name -** "name" is the distinguished name to look up (in ascii) -*/ -extern CERTCertificate * -CERT_FindCertByNameString (CERTCertDBHandle *handle, char *name); - -/* -** Find a certificate in the database by name and keyid -** "name" is the distinguished name to look up -** "keyID" is the value of the subjectKeyID to match -*/ -extern CERTCertificate * -CERT_FindCertByKeyID (CERTCertDBHandle *handle, SECItem *name, SECItem *keyID); - -/* -** Generate a certificate key from the issuer and serialnumber, then look it -** up in the database. Return the cert if found. -** "issuerAndSN" is the issuer and serial number to look for -*/ -extern CERTCertificate * -CERT_FindCertByIssuerAndSN (CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN); - -/* -** Find a certificate in the database by a subject key ID -** "subjKeyID" is the subject Key ID to look for -*/ -extern CERTCertificate * -CERT_FindCertBySubjectKeyID (CERTCertDBHandle *handle, SECItem *subjKeyID); - -/* -** Encode Certificate SKID (Subject Key ID) extension. -** -*/ -extern SECStatus -CERT_EncodeSubjectKeyID(PLArenaPool *arena, const SECItem* srcString, - SECItem *encodedValue); - -/* -** Find a certificate in the database by a nickname -** "nickname" is the ascii string nickname to look for -*/ -extern CERTCertificate * -CERT_FindCertByNickname (CERTCertDBHandle *handle, const char *nickname); - -/* -** Find a certificate in the database by a DER encoded certificate -** "derCert" is the DER encoded certificate -*/ -extern CERTCertificate * -CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert); - -/* -** Find a certificate in the database by a email address -** "emailAddr" is the email address to look up -*/ -CERTCertificate * -CERT_FindCertByEmailAddr(CERTCertDBHandle *handle, char *emailAddr); - -/* -** Find a certificate in the database by a email address or nickname -** "name" is the email address or nickname to look up -*/ -CERTCertificate * -CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name); - -/* -** Find a certificate in the database by a email address or nickname -** and require it to have the given usage. -** "name" is the email address or nickname to look up -*/ -CERTCertificate * -CERT_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle, - const char *name, - SECCertUsage lookingForUsage); - -/* -** Find a certificate in the database by a digest of a subject public key -** "spkDigest" is the digest to look up -*/ -extern CERTCertificate * -CERT_FindCertBySPKDigest(CERTCertDBHandle *handle, SECItem *spkDigest); - -/* - * Find the issuer of a cert - */ -CERTCertificate * -CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, SECCertUsage usage); - -/* -** Check the validity times of a certificate vs. time 't', allowing -** some slop for broken clocks and stuff. -** "cert" is the certificate to be checked -** "t" is the time to check against -** "allowOverride" if true then check to see if the invalidity has -** been overridden by the user. -*/ -extern SECCertTimeValidity CERT_CheckCertValidTimes(CERTCertificate *cert, - PRTime t, - PRBool allowOverride); - -/* -** WARNING - this function is deprecated, and will either go away or have -** a new API in the near future. -** -** Check the validity times of a certificate vs. the current time, allowing -** some slop for broken clocks and stuff. -** "cert" is the certificate to be checked -*/ -extern SECStatus CERT_CertTimesValid(CERTCertificate *cert); - -/* -** Extract the validity times from a certificate -** "c" is the certificate -** "notBefore" is the start of the validity period -** "notAfter" is the end of the validity period -*/ -extern SECStatus -CERT_GetCertTimes (CERTCertificate *c, PRTime *notBefore, PRTime *notAfter); - -/* -** Extract the issuer and serial number from a certificate -*/ -extern CERTIssuerAndSN *CERT_GetCertIssuerAndSN(PLArenaPool *, - CERTCertificate *); - -/* -** verify the signature of a signed data object with a given certificate -** "sd" the signed data object to be verified -** "cert" the certificate to use to check the signature -*/ -extern SECStatus CERT_VerifySignedData(CERTSignedData *sd, - CERTCertificate *cert, - PRTime t, - void *wincx); -/* -** verify the signature of a signed data object with the given DER publickey -*/ -extern SECStatus -CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd, - CERTSubjectPublicKeyInfo *pubKeyInfo, - void *wincx); - -/* -** verify the signature of a signed data object with a SECKEYPublicKey. -*/ -extern SECStatus -CERT_VerifySignedDataWithPublicKey(CERTSignedData *sd, - SECKEYPublicKey *pubKey, void *wincx); - -/* -** NEW FUNCTIONS with new bit-field-FIELD SECCertificateUsage - please use -** verify a certificate by checking validity times against a certain time, -** that we trust the issuer, and that the signature on the certificate is -** valid. -** "cert" the certificate to verify -** "checkSig" only check signatures if true -*/ -extern SECStatus -CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert, - PRBool checkSig, SECCertificateUsage requiredUsages, - PRTime t, void *wincx, CERTVerifyLog *log, - SECCertificateUsage* returnedUsages); - -/* same as above, but uses current time */ -extern SECStatus -CERT_VerifyCertificateNow(CERTCertDBHandle *handle, CERTCertificate *cert, - PRBool checkSig, SECCertificateUsage requiredUsages, - void *wincx, SECCertificateUsage* returnedUsages); - -/* -** Verify that a CA cert can certify some (unspecified) leaf cert for a given -** purpose. This is used by UI code to help identify where a chain may be -** broken and why. This takes identical parameters to CERT_VerifyCert -*/ -extern SECStatus -CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, CERTCertificate *cert, - PRBool checkSig, SECCertUsage certUsage, PRTime t, - void *wincx, CERTVerifyLog *log); - -/* -** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE -** verify a certificate by checking validity times against a certain time, -** that we trust the issuer, and that the signature on the certificate is -** valid. -** "cert" the certificate to verify -** "checkSig" only check signatures if true -*/ -extern SECStatus -CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert, - PRBool checkSig, SECCertUsage certUsage, PRTime t, - void *wincx, CERTVerifyLog *log); - -/* same as above, but uses current time */ -extern SECStatus -CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert, - PRBool checkSig, SECCertUsage certUsage, void *wincx); - -SECStatus -CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, - PRBool checkSig, SECCertUsage certUsage, PRTime t, - void *wincx, CERTVerifyLog *log); - -/* -** Read a base64 ascii encoded DER certificate and convert it to our -** internal format. -** "certstr" is a null-terminated string containing the certificate -*/ -extern CERTCertificate *CERT_ConvertAndDecodeCertificate(char *certstr); - -/* -** Read a certificate in some foreign format, and convert it to our -** internal format. -** "certbuf" is the buffer containing the certificate -** "certlen" is the length of the buffer -** NOTE - currently supports netscape base64 ascii encoded raw certs -** and netscape binary DER typed files. -*/ -extern CERTCertificate *CERT_DecodeCertFromPackage(char *certbuf, int certlen); - -extern SECStatus -CERT_ImportCAChain (SECItem *certs, int numcerts, SECCertUsage certUsage); - -extern SECStatus -CERT_ImportCAChainTrusted(SECItem *certs, int numcerts, SECCertUsage certUsage); - -/* -** Read a certificate chain in some foreign format, and pass it to a -** callback function. -** "certbuf" is the buffer containing the certificate -** "certlen" is the length of the buffer -** "f" is the callback function -** "arg" is the callback argument -*/ -typedef SECStatus (PR_CALLBACK *CERTImportCertificateFunc) - (void *arg, SECItem **certs, int numcerts); - -extern SECStatus -CERT_DecodeCertPackage(char *certbuf, int certlen, CERTImportCertificateFunc f, - void *arg); - -/* -** Returns the value of an AVA. This was a formerly static -** function that has been exposed due to the need to decode -** and convert unicode strings to UTF8. -** -** XXX This function resides in certhtml.c, should it be -** moved elsewhere? -*/ -extern SECItem *CERT_DecodeAVAValue(const SECItem *derAVAValue); - - - -/* -** extract various element strings from a distinguished name. -** "name" the distinguished name -*/ - -extern char *CERT_GetCertificateEmailAddress(CERTCertificate *cert); - -extern char *CERT_GetCertEmailAddress(CERTName *name); - -extern const char * CERT_GetFirstEmailAddress(CERTCertificate * cert); - -extern const char * CERT_GetNextEmailAddress(CERTCertificate * cert, - const char * prev); - -/* The return value must be freed with PORT_Free. */ -extern char *CERT_GetCommonName(CERTName *name); - -extern char *CERT_GetCountryName(CERTName *name); - -extern char *CERT_GetLocalityName(CERTName *name); - -extern char *CERT_GetStateName(CERTName *name); - -extern char *CERT_GetOrgName(CERTName *name); - -extern char *CERT_GetOrgUnitName(CERTName *name); - -extern char *CERT_GetDomainComponentName(CERTName *name); - -extern char *CERT_GetCertUid(CERTName *name); - -/* manipulate the trust parameters of a certificate */ - -extern SECStatus CERT_GetCertTrust(CERTCertificate *cert, CERTCertTrust *trust); - -extern SECStatus -CERT_ChangeCertTrust (CERTCertDBHandle *handle, CERTCertificate *cert, - CERTCertTrust *trust); - -extern SECStatus -CERT_ChangeCertTrustByUsage(CERTCertDBHandle *certdb, CERTCertificate *cert, - SECCertUsage usage); - -/************************************************************************* - * - * manipulate the extensions of a certificate - * - ************************************************************************/ - -/* -** Set up a cert for adding X509v3 extensions. Returns an opaque handle -** used by the next two routines. -** "cert" is the certificate we are adding extensions to -*/ -extern void *CERT_StartCertExtensions(CERTCertificate *cert); - -/* -** Add an extension to a certificate. -** "exthandle" is the handle returned by the previous function -** "idtag" is the integer tag for the OID that should ID this extension -** "value" is the value of the extension -** "critical" is the critical extension flag -** "copyData" is a flag indicating whether the value data should be -** copied. -*/ -extern SECStatus CERT_AddExtension (void *exthandle, int idtag, - SECItem *value, PRBool critical, PRBool copyData); - -extern SECStatus CERT_AddExtensionByOID (void *exthandle, SECItem *oid, - SECItem *value, PRBool critical, PRBool copyData); - -extern SECStatus CERT_EncodeAndAddExtension - (void *exthandle, int idtag, void *value, PRBool critical, - const SEC_ASN1Template *atemplate); - -extern SECStatus CERT_EncodeAndAddBitStrExtension - (void *exthandle, int idtag, SECItem *value, PRBool critical); - - -extern SECStatus -CERT_EncodeAltNameExtension(PLArenaPool *arena, CERTGeneralName *value, SECItem *encodedValue); - - -/* -** Finish adding cert extensions. Does final processing on extension -** data, putting it in the right format, and freeing any temporary -** storage. -** "exthandle" is the handle used to add extensions to a certificate -*/ -extern SECStatus CERT_FinishExtensions(void *exthandle); - -/* -** Merge an external list of extensions into a cert's extension list, adding one -** only when its OID matches none of the cert's existing extensions. Call this -** immediately before calling CERT_FinishExtensions(). -*/ -SECStatus -CERT_MergeExtensions(void *exthandle, CERTCertExtension **exts); - -/* If the extension is found, return its criticality and value. -** This allocate storage for the returning extension value. -*/ -extern SECStatus CERT_GetExtenCriticality - (CERTCertExtension **extensions, int tag, PRBool *isCritical); - -extern void -CERT_DestroyOidSequence(CERTOidSequence *oidSeq); - -/**************************************************************************** - * - * DER encode and decode extension values - * - ****************************************************************************/ - -/* Encode the value of the basicConstraint extension. -** arena - where to allocate memory for the encoded value. -** value - extension value to encode -** encodedValue - output encoded value -*/ -extern SECStatus CERT_EncodeBasicConstraintValue - (PLArenaPool *arena, CERTBasicConstraints *value, SECItem *encodedValue); - -/* -** Encode the value of the authorityKeyIdentifier extension. -*/ -extern SECStatus CERT_EncodeAuthKeyID - (PLArenaPool *arena, CERTAuthKeyID *value, SECItem *encodedValue); - -/* -** Encode the value of the crlDistributionPoints extension. -*/ -extern SECStatus CERT_EncodeCRLDistributionPoints - (PLArenaPool *arena, CERTCrlDistributionPoints *value,SECItem *derValue); - -/* -** Decodes a DER encoded basicConstaint extension value into a readable format -** value - decoded value -** encodedValue - value to decoded -*/ -extern SECStatus CERT_DecodeBasicConstraintValue - (CERTBasicConstraints *value, SECItem *encodedValue); - -/* Decodes a DER encoded authorityKeyIdentifier extension value into a -** readable format. -** arena - where to allocate memory for the decoded value -** encodedValue - value to be decoded -** Returns a CERTAuthKeyID structure which contains the decoded value -*/ -extern CERTAuthKeyID *CERT_DecodeAuthKeyID - (PLArenaPool *arena, SECItem *encodedValue); - - -/* Decodes a DER encoded crlDistributionPoints extension value into a -** readable format. -** arena - where to allocate memory for the decoded value -** der - value to be decoded -** Returns a CERTCrlDistributionPoints structure which contains the -** decoded value -*/ -extern CERTCrlDistributionPoints * CERT_DecodeCRLDistributionPoints - (PLArenaPool *arena, SECItem *der); - -/* Extract certain name type from a generalName */ -extern void *CERT_GetGeneralNameByType - (CERTGeneralName *genNames, CERTGeneralNameType type, PRBool derFormat); - - -extern CERTOidSequence * -CERT_DecodeOidSequence(SECItem *seqItem); - - - - -/**************************************************************************** - * - * Find extension values of a certificate - * - ***************************************************************************/ - -extern SECStatus CERT_FindCertExtension - (CERTCertificate *cert, int tag, SECItem *value); - -extern SECStatus CERT_FindNSCertTypeExtension - (CERTCertificate *cert, SECItem *value); - -extern char * CERT_FindNSStringExtension (CERTCertificate *cert, int oidtag); - -extern SECStatus CERT_FindIssuerCertExtension - (CERTCertificate *cert, int tag, SECItem *value); - -extern SECStatus CERT_FindCertExtensionByOID - (CERTCertificate *cert, SECItem *oid, SECItem *value); - -extern char *CERT_FindCertURLExtension (CERTCertificate *cert, int tag, - int catag); - -/* Returns the decoded value of the authKeyID extension. -** Note that this uses passed in the arena to allocate storage for the result -*/ -extern CERTAuthKeyID * CERT_FindAuthKeyIDExten (PLArenaPool *arena,CERTCertificate *cert); - -/* Returns the decoded value of the basicConstraint extension. - */ -extern SECStatus CERT_FindBasicConstraintExten - (CERTCertificate *cert, CERTBasicConstraints *value); - -/* Returns the decoded value of the crlDistributionPoints extension. -** Note that the arena in cert is used to allocate storage for the result -*/ -extern CERTCrlDistributionPoints * CERT_FindCRLDistributionPoints - (CERTCertificate *cert); - -/* Returns value of the keyUsage extension. This uses PR_Alloc to allocate -** buffer for the decoded value. The caller should free up the storage -** allocated in value->data. -*/ -extern SECStatus CERT_FindKeyUsageExtension (CERTCertificate *cert, - SECItem *value); - -/* Return the decoded value of the subjectKeyID extension. The caller should -** free up the storage allocated in retItem->data. -*/ -extern SECStatus CERT_FindSubjectKeyIDExtension (CERTCertificate *cert, - SECItem *retItem); - -/* -** If cert is a v3 certificate, and a critical keyUsage extension is included, -** then check the usage against the extension value. If a non-critical -** keyUsage extension is included, this will return SECSuccess without -** checking, since the extension is an advisory field, not a restriction. -** If cert is not a v3 certificate, this will return SECSuccess. -** cert - certificate -** usage - one of the x.509 v3 the Key Usage Extension flags -*/ -extern SECStatus CERT_CheckCertUsage (CERTCertificate *cert, - unsigned char usage); - -/**************************************************************************** - * - * CRL v2 Extensions supported routines - * - ****************************************************************************/ - -extern SECStatus CERT_FindCRLExtensionByOID - (CERTCrl *crl, SECItem *oid, SECItem *value); - -extern SECStatus CERT_FindCRLExtension - (CERTCrl *crl, int tag, SECItem *value); - -extern SECStatus - CERT_FindInvalidDateExten (CERTCrl *crl, PRTime *value); - -/* -** Set up a crl for adding X509v3 extensions. Returns an opaque handle -** used by routines that take an exthandle (void*) argument . -** "crl" is the CRL we are adding extensions to -*/ -extern void *CERT_StartCRLExtensions(CERTCrl *crl); - -/* -** Set up a crl entry for adding X509v3 extensions. Returns an opaque handle -** used by routines that take an exthandle (void*) argument . -** "crl" is the crl we are adding certs entries to -** "entry" is the crl entry we are adding extensions to -*/ -extern void *CERT_StartCRLEntryExtensions(CERTCrl *crl, CERTCrlEntry *entry); - -extern CERTCertNicknames *CERT_GetCertNicknames (CERTCertDBHandle *handle, - int what, void *wincx); - -/* -** Finds the crlNumber extension and decodes its value into 'value' -*/ -extern SECStatus CERT_FindCRLNumberExten (PLArenaPool *arena, CERTCrl *crl, - SECItem *value); - -extern SECStatus CERT_FindCRLEntryReasonExten (CERTCrlEntry *crlEntry, - CERTCRLEntryReasonCode *value); - -extern void CERT_FreeNicknames(CERTCertNicknames *nicknames); - -extern PRBool CERT_CompareCerts(CERTCertificate *c1, CERTCertificate *c2); - -extern PRBool CERT_CompareCertsForRedirection(CERTCertificate *c1, - CERTCertificate *c2); - -/* -** Generate an array of the Distinguished Names that the given cert database -** "trusts" -*/ -extern CERTDistNames *CERT_GetSSLCACerts(CERTCertDBHandle *handle); - -extern void CERT_FreeDistNames(CERTDistNames *names); - -/* Duplicate distinguished name array */ -extern CERTDistNames *CERT_DupDistNames(CERTDistNames *orig); - -/* -** Generate an array of Distinguished names from an array of nicknames -*/ -extern CERTDistNames *CERT_DistNamesFromNicknames - (CERTCertDBHandle *handle, char **nicknames, int nnames); - -/* -** Generate an array of Distinguished names from a list of certs. -*/ -extern CERTDistNames *CERT_DistNamesFromCertList(CERTCertList *list); - -/* -** Generate a certificate chain from a certificate. -*/ -extern CERTCertificateList * -CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage, - PRBool includeRoot); - -extern CERTCertificateList * -CERT_CertListFromCert(CERTCertificate *cert); - -extern CERTCertificateList * -CERT_DupCertList(const CERTCertificateList * oldList); - -extern void CERT_DestroyCertificateList(CERTCertificateList *list); - -/* -** is cert a user cert? i.e. does it have CERTDB_USER trust, -** i.e. a private key? -*/ -PRBool CERT_IsUserCert(CERTCertificate* cert); - -/* is cert a newer than cert b? */ -PRBool CERT_IsNewer(CERTCertificate *certa, CERTCertificate *certb); - -/* currently a stub for address book */ -PRBool -CERT_IsCertRevoked(CERTCertificate *cert); - -void -CERT_DestroyCertArray(CERTCertificate **certs, unsigned int ncerts); - -/* convert an email address to lower case */ -char *CERT_FixupEmailAddr(const char *emailAddr); - -/* decode string representation of trust flags into trust struct */ -SECStatus -CERT_DecodeTrustString(CERTCertTrust *trust, const char *trusts); - -/* encode trust struct into string representation of trust flags */ -char * -CERT_EncodeTrustString(CERTCertTrust *trust); - -/* find the next or prev cert in a subject list */ -CERTCertificate * -CERT_PrevSubjectCert(CERTCertificate *cert); -CERTCertificate * -CERT_NextSubjectCert(CERTCertificate *cert); - -/* - * import a collection of certs into the temporary or permanent cert - * database - */ -SECStatus -CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage, - unsigned int ncerts, SECItem **derCerts, - CERTCertificate ***retCerts, PRBool keepCerts, - PRBool caOnly, char *nickname); - -char * -CERT_MakeCANickname(CERTCertificate *cert); - -PRBool -CERT_IsCACert(CERTCertificate *cert, unsigned int *rettype); - -PRBool -CERT_IsCADERCert(SECItem *derCert, unsigned int *rettype); - -PRBool -CERT_IsRootDERCert(SECItem *derCert); - -SECStatus -CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile, - SECItem *profileTime); - -/* - * find the smime symmetric capabilities profile for a given cert - */ -SECItem * -CERT_FindSMimeProfile(CERTCertificate *cert); - -SECStatus -CERT_AddNewCerts(CERTCertDBHandle *handle); - -CERTCertificatePolicies * -CERT_DecodeCertificatePoliciesExtension(SECItem *extnValue); - -void -CERT_DestroyCertificatePoliciesExtension(CERTCertificatePolicies *policies); - -CERTCertificatePolicyMappings * -CERT_DecodePolicyMappingsExtension(SECItem *encodedCertPolicyMaps); - -SECStatus -CERT_DestroyPolicyMappingsExtension(CERTCertificatePolicyMappings *mappings); - -SECStatus -CERT_DecodePolicyConstraintsExtension( - CERTCertificatePolicyConstraints *decodedValue, SECItem *encodedValue); - -SECStatus CERT_DecodeInhibitAnyExtension - (CERTCertificateInhibitAny *decodedValue, SECItem *extnValue); - -CERTUserNotice * -CERT_DecodeUserNotice(SECItem *noticeItem); - -extern CERTGeneralName * -CERT_DecodeAltNameExtension(PLArenaPool *reqArena, SECItem *EncodedAltName); - -extern CERTNameConstraints * -CERT_DecodeNameConstraintsExtension(PLArenaPool *arena, - SECItem *encodedConstraints); - -/* returns addr of a NULL termainated array of pointers to CERTAuthInfoAccess */ -extern CERTAuthInfoAccess ** -CERT_DecodeAuthInfoAccessExtension(PLArenaPool *reqArena, - SECItem *encodedExtension); - -extern CERTPrivKeyUsagePeriod * -CERT_DecodePrivKeyUsagePeriodExtension(PLArenaPool *arena, SECItem *extnValue); - -extern CERTGeneralName * -CERT_GetNextGeneralName(CERTGeneralName *current); - -extern CERTGeneralName * -CERT_GetPrevGeneralName(CERTGeneralName *current); - -CERTNameConstraint * -CERT_GetNextNameConstraint(CERTNameConstraint *current); - -CERTNameConstraint * -CERT_GetPrevNameConstraint(CERTNameConstraint *current); - -void -CERT_DestroyUserNotice(CERTUserNotice *userNotice); - -typedef char * (* CERTPolicyStringCallback)(char *org, - unsigned long noticeNumber, - void *arg); -void -CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg); - -char * -CERT_GetCertCommentString(CERTCertificate *cert); - -PRBool -CERT_GovtApprovedBitSet(CERTCertificate *cert); - -SECStatus -CERT_AddPermNickname(CERTCertificate *cert, char *nickname); - -CERTCertList * -CERT_MatchUserCert(CERTCertDBHandle *handle, - SECCertUsage usage, - int nCANames, char **caNames, - void *proto_win); - -CERTCertList * -CERT_NewCertList(void); - -void -CERT_DestroyCertList(CERTCertList *certs); - -/* remove the node and free the cert */ -void -CERT_RemoveCertListNode(CERTCertListNode *node); - -SECStatus -CERT_AddCertToListTail(CERTCertList *certs, CERTCertificate *cert); - -SECStatus -CERT_AddCertToListHead(CERTCertList *certs, CERTCertificate *cert); - -SECStatus -CERT_AddCertToListTailWithData(CERTCertList *certs, CERTCertificate *cert, - void *appData); - -SECStatus -CERT_AddCertToListHeadWithData(CERTCertList *certs, CERTCertificate *cert, - void *appData); - -typedef PRBool (* CERTSortCallback)(CERTCertificate *certa, - CERTCertificate *certb, - void *arg); -SECStatus -CERT_AddCertToListSorted(CERTCertList *certs, CERTCertificate *cert, - CERTSortCallback f, void *arg); - -/* callback for CERT_AddCertToListSorted that sorts based on validity - * period and a given time. - */ -PRBool -CERT_SortCBValidity(CERTCertificate *certa, - CERTCertificate *certb, - void *arg); - -SECStatus -CERT_CheckForEvilCert(CERTCertificate *cert); - -CERTGeneralName * -CERT_GetCertificateNames(CERTCertificate *cert, PLArenaPool *arena); - -CERTGeneralName * -CERT_GetConstrainedCertificateNames(CERTCertificate *cert, PLArenaPool *arena, - PRBool includeSubjectCommonName); - -/* - * Creates or adds to a list of all certs with a give subject name, sorted by - * validity time, newest first. Invalid certs are considered older than - * valid certs. If validOnly is set, do not include invalid certs on list. - */ -CERTCertList * -CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle, - SECItem *name, PRTime sorttime, PRBool validOnly); - -/* - * remove certs from a list that don't have keyUsage and certType - * that match the given usage. - */ -SECStatus -CERT_FilterCertListByUsage(CERTCertList *certList, SECCertUsage usage, - PRBool ca); - -/* - * check the key usage of a cert against a set of required values - */ -SECStatus -CERT_CheckKeyUsage(CERTCertificate *cert, unsigned int requiredUsage); - -/* - * return required key usage and cert type based on cert usage - */ -SECStatus -CERT_KeyUsageAndTypeForCertUsage(SECCertUsage usage, - PRBool ca, - unsigned int *retKeyUsage, - unsigned int *retCertType); -/* - * return required trust flags for various cert usages for CAs - */ -SECStatus -CERT_TrustFlagsForCACertUsage(SECCertUsage usage, - unsigned int *retFlags, - SECTrustType *retTrustType); - -/* - * Find all user certificates that match the given criteria. - * - * "handle" - database to search - * "usage" - certificate usage to match - * "oneCertPerName" - if set then only return the "best" cert per - * name - * "validOnly" - only return certs that are curently valid - * "proto_win" - window handle passed to pkcs11 - */ -CERTCertList * -CERT_FindUserCertsByUsage(CERTCertDBHandle *handle, - SECCertUsage usage, - PRBool oneCertPerName, - PRBool validOnly, - void *proto_win); - -/* - * Find a user certificate that matchs the given criteria. - * - * "handle" - database to search - * "nickname" - nickname to match - * "usage" - certificate usage to match - * "validOnly" - only return certs that are curently valid - * "proto_win" - window handle passed to pkcs11 - */ -CERTCertificate * -CERT_FindUserCertByUsage(CERTCertDBHandle *handle, - const char *nickname, - SECCertUsage usage, - PRBool validOnly, - void *proto_win); - -/* - * Filter a list of certificates, removing those certs that do not have - * one of the named CA certs somewhere in their cert chain. - * - * "certList" - the list of certificates to filter - * "nCANames" - number of CA names - * "caNames" - array of CA names in string(rfc 1485) form - * "usage" - what use the certs are for, this is used when - * selecting CA certs - */ -SECStatus -CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames, - char **caNames, SECCertUsage usage); - -/* - * Filter a list of certificates, removing those certs that aren't user certs - */ -SECStatus -CERT_FilterCertListForUserCerts(CERTCertList *certList); - -/* - * Collect the nicknames from all certs in a CertList. If the cert is not - * valid, append a string to that nickname. - * - * "certList" - the list of certificates - * "expiredString" - the string to append to the nickname of any expired cert - * "notYetGoodString" - the string to append to the nickname of any cert - * that is not yet valid - */ -CERTCertNicknames * -CERT_NicknameStringsFromCertList(CERTCertList *certList, char *expiredString, - char *notYetGoodString); - -/* - * Extract the nickname from a nickmake string that may have either - * expiredString or notYetGoodString appended. - * - * Args: - * "namestring" - the string containing the nickname, and possibly - * one of the validity label strings - * "expiredString" - the expired validity label string - * "notYetGoodString" - the not yet good validity label string - * - * Returns the raw nickname - */ -char * -CERT_ExtractNicknameString(char *namestring, char *expiredString, - char *notYetGoodString); - -/* - * Given a certificate, return a string containing the nickname, and possibly - * one of the validity strings, based on the current validity state of the - * certificate. - * - * "arena" - arena to allocate returned string from. If NULL, then heap - * is used. - * "cert" - the cert to get nickname from - * "expiredString" - the string to append to the nickname if the cert is - * expired. - * "notYetGoodString" - the string to append to the nickname if the cert is - * not yet good. - */ -char * -CERT_GetCertNicknameWithValidity(PLArenaPool *arena, CERTCertificate *cert, - char *expiredString, char *notYetGoodString); - -/* - * Return the string representation of a DER encoded distinguished name - * "dername" - The DER encoded name to convert - */ -char * -CERT_DerNameToAscii(SECItem *dername); - -/* - * Supported usage values and types: - * certUsageSSLClient - * certUsageSSLServer - * certUsageSSLServerWithStepUp - * certUsageEmailSigner - * certUsageEmailRecipient - * certUsageObjectSigner - */ - -CERTCertificate * -CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName, - CERTCertOwner owner, SECCertUsage usage, - PRBool preferTrusted, PRTime validTime, PRBool validOnly); - -/* - * Acquire the global lock on the cert database. - * This lock is currently used for the following operations: - * adding or deleting a cert to either the temp or perm databases - * converting a temp to perm or perm to temp - * changing(maybe just adding?) the trust of a cert - * adjusting the reference count of a cert - */ -void -CERT_LockDB(CERTCertDBHandle *handle); - -/* - * Free the global cert database lock. - */ -void -CERT_UnlockDB(CERTCertDBHandle *handle); - -/* - * Get the certificate status checking configuratino data for - * the certificate database - */ -CERTStatusConfig * -CERT_GetStatusConfig(CERTCertDBHandle *handle); - -/* - * Set the certificate status checking information for the - * database. The input structure becomes part of the certificate - * database and will be freed by calling the 'Destroy' function in - * the configuration object. - */ -void -CERT_SetStatusConfig(CERTCertDBHandle *handle, CERTStatusConfig *config); - - - -/* - * Acquire the cert reference count lock - * There is currently one global lock for all certs, but I'm putting a cert - * arg here so that it will be easy to make it per-cert in the future if - * that turns out to be necessary. - */ -void -CERT_LockCertRefCount(CERTCertificate *cert); - -/* - * Free the cert reference count lock - */ -void -CERT_UnlockCertRefCount(CERTCertificate *cert); - -/* - * Acquire the cert trust lock - * There is currently one global lock for all certs, but I'm putting a cert - * arg here so that it will be easy to make it per-cert in the future if - * that turns out to be necessary. - */ -void -CERT_LockCertTrust(CERTCertificate *cert); - -/* - * Free the cert trust lock - */ -void -CERT_UnlockCertTrust(CERTCertificate *cert); - -/* - * Digest the cert's subject public key using the specified algorithm. - * The necessary storage for the digest data is allocated. If "fill" is - * non-null, the data is put there, otherwise a SECItem is allocated. - * Allocation from "arena" if it is non-null, heap otherwise. Any problem - * results in a NULL being returned (and an appropriate error set). - */ -extern SECItem * -CERT_GetSPKIDigest(PLArenaPool *arena, const CERTCertificate *cert, - SECOidTag digestAlg, SECItem *fill); - - -SECStatus CERT_CheckCRL(CERTCertificate* cert, CERTCertificate* issuer, - const SECItem* dp, PRTime t, void* wincx); - - -/* - * Add a CERTNameConstraint to the CERTNameConstraint list - */ -extern CERTNameConstraint * -CERT_AddNameConstraint(CERTNameConstraint *list, - CERTNameConstraint *constraint); - -/* - * Allocate space and copy CERTNameConstraint from src to dest. - * Arena is used to allocate result(if dest eq NULL) and its members - * SECItem data. - */ -extern CERTNameConstraint * -CERT_CopyNameConstraint(PLArenaPool *arena, - CERTNameConstraint *dest, - CERTNameConstraint *src); - -/* - * Verify name against all the constraints relevant to that type of - * the name. - */ -extern SECStatus -CERT_CheckNameSpace(PLArenaPool *arena, - CERTNameConstraints *constraints, - CERTGeneralName *currentName); - -/* - * Extract and allocate the name constraints extension from the CA cert. - */ -extern SECStatus -CERT_FindNameConstraintsExten(PLArenaPool *arena, - CERTCertificate *cert, - CERTNameConstraints **constraints); - -/* - * Initialize a new GERTGeneralName fields (link) - */ -extern CERTGeneralName * -CERT_NewGeneralName(PLArenaPool *arena, CERTGeneralNameType type); - -/* - * PKIX extension encoding routines - */ -extern SECStatus -CERT_EncodePolicyConstraintsExtension(PLArenaPool *arena, - CERTCertificatePolicyConstraints *constr, - SECItem *dest); -extern SECStatus -CERT_EncodeInhibitAnyExtension(PLArenaPool *arena, - CERTCertificateInhibitAny *inhibitAny, - SECItem *dest); -extern SECStatus -CERT_EncodePolicyMappingExtension(PLArenaPool *arena, - CERTCertificatePolicyMappings *maps, - SECItem *dest); - -extern SECStatus CERT_EncodeInfoAccessExtension(PLArenaPool *arena, - CERTAuthInfoAccess **info, - SECItem *dest); -extern SECStatus -CERT_EncodeUserNotice(PLArenaPool *arena, - CERTUserNotice *notice, - SECItem *dest); - -extern SECStatus -CERT_EncodeDisplayText(PLArenaPool *arena, - SECItem *text, - SECItem *dest); - -extern SECStatus -CERT_EncodeCertPoliciesExtension(PLArenaPool *arena, - CERTPolicyInfo **info, - SECItem *dest); -extern SECStatus -CERT_EncodeNoticeReference(PLArenaPool *arena, - CERTNoticeReference *reference, - SECItem *dest); - -/* - * Returns a pointer to a static structure. - */ -extern const CERTRevocationFlags* -CERT_GetPKIXVerifyNistRevocationPolicy(void); - -/* - * Returns a pointer to a static structure. - */ -extern const CERTRevocationFlags* -CERT_GetClassicOCSPEnabledSoftFailurePolicy(void); - -/* - * Returns a pointer to a static structure. - */ -extern const CERTRevocationFlags* -CERT_GetClassicOCSPEnabledHardFailurePolicy(void); - -/* - * Returns a pointer to a static structure. - */ -extern const CERTRevocationFlags* -CERT_GetClassicOCSPDisabledPolicy(void); - -/* - * Verify a Cert with libpkix - * paramsIn control the verification options. If a value isn't specified - * in paramsIn, it reverts to the application default. - * paramsOut specifies the parameters the caller would like to get back. - * the caller may pass NULL, in which case no parameters are returned. - */ -extern SECStatus CERT_PKIXVerifyCert( - CERTCertificate *cert, - SECCertificateUsage usages, - CERTValInParam *paramsIn, - CERTValOutParam *paramsOut, - void *wincx); - -/* Makes old cert validation APIs(CERT_VerifyCert, CERT_VerifyCertificate) - * to use libpkix validation engine. The function should be called ones at - * application initialization time. - * Function is not thread safe.*/ -extern SECStatus CERT_SetUsePKIXForValidation(PRBool enable); - -/* The function return PR_TRUE if cert validation should use - * libpkix cert validation engine. */ -extern PRBool CERT_GetUsePKIXForValidation(void); - -/* - * Allocate a parameter container of type CERTRevocationFlags, - * and allocate the inner arrays of the given sizes. - * To cleanup call CERT_DestroyCERTRevocationFlags. - */ -extern CERTRevocationFlags * -CERT_AllocCERTRevocationFlags( - PRUint32 number_leaf_methods, PRUint32 number_leaf_pref_methods, - PRUint32 number_chain_methods, PRUint32 number_chain_pref_methods); - -/* - * Destroy the arrays inside flags, - * and destroy the object pointed to by flags, too. - */ -extern void -CERT_DestroyCERTRevocationFlags(CERTRevocationFlags *flags); - -SEC_END_PROTOS - -#endif /* _CERT_H_ */ diff --git a/security/nss/lib/certdb/certdb.c b/security/nss/lib/certdb/certdb.c deleted file mode 100644 index 809a96598..000000000 --- a/security/nss/lib/certdb/certdb.c +++ /dev/null @@ -1,3273 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * Certificate handling code - * - * $Id$ - */ - -#include "nssilock.h" -#include "prmon.h" -#include "prtime.h" -#include "cert.h" -#include "certi.h" -#include "secder.h" -#include "secoid.h" -#include "secasn1.h" -#include "genname.h" -#include "keyhi.h" -#include "secitem.h" -#include "certdb.h" -#include "prprf.h" -#include "sechash.h" -#include "prlong.h" -#include "certxutl.h" -#include "portreg.h" -#include "secerr.h" -#include "sslerr.h" -#include "pk11func.h" -#include "xconst.h" /* for CERT_DecodeAltNameExtension */ - -#include "pki.h" -#include "pki3hack.h" - -SEC_ASN1_MKSUB(CERT_TimeChoiceTemplate) -SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) -SEC_ASN1_MKSUB(SEC_BitStringTemplate) -SEC_ASN1_MKSUB(SEC_IntegerTemplate) -SEC_ASN1_MKSUB(SEC_SkipTemplate) - -/* - * Certificate database handling code - */ - - -const SEC_ASN1Template CERT_CertExtensionTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTCertExtension) }, - { SEC_ASN1_OBJECT_ID, - offsetof(CERTCertExtension,id) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */ - offsetof(CERTCertExtension,critical) }, - { SEC_ASN1_OCTET_STRING, - offsetof(CERTCertExtension,value) }, - { 0, } -}; - -const SEC_ASN1Template CERT_SequenceOfCertExtensionTemplate[] = { - { SEC_ASN1_SEQUENCE_OF, 0, CERT_CertExtensionTemplate } -}; - -const SEC_ASN1Template CERT_TimeChoiceTemplate[] = { - { SEC_ASN1_CHOICE, offsetof(SECItem, type), 0, sizeof(SECItem) }, - { SEC_ASN1_UTC_TIME, 0, 0, siUTCTime }, - { SEC_ASN1_GENERALIZED_TIME, 0, 0, siGeneralizedTime }, - { 0 } -}; - -const SEC_ASN1Template CERT_ValidityTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTValidity) }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(CERTValidity,notBefore), - SEC_ASN1_SUB(CERT_TimeChoiceTemplate), 0 }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(CERTValidity,notAfter), - SEC_ASN1_SUB(CERT_TimeChoiceTemplate), 0 }, - { 0 } -}; - -const SEC_ASN1Template CERT_CertificateTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTCertificate) }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | - SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, /* XXX DER_DEFAULT */ - offsetof(CERTCertificate,version), - SEC_ASN1_SUB(SEC_IntegerTemplate) }, - { SEC_ASN1_INTEGER, - offsetof(CERTCertificate,serialNumber) }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(CERTCertificate,signature), - SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, - { SEC_ASN1_SAVE, - offsetof(CERTCertificate,derIssuer) }, - { SEC_ASN1_INLINE, - offsetof(CERTCertificate,issuer), - CERT_NameTemplate }, - { SEC_ASN1_INLINE, - offsetof(CERTCertificate,validity), - CERT_ValidityTemplate }, - { SEC_ASN1_SAVE, - offsetof(CERTCertificate,derSubject) }, - { SEC_ASN1_INLINE, - offsetof(CERTCertificate,subject), - CERT_NameTemplate }, - { SEC_ASN1_SAVE, - offsetof(CERTCertificate,derPublicKey) }, - { SEC_ASN1_INLINE, - offsetof(CERTCertificate,subjectPublicKeyInfo), - CERT_SubjectPublicKeyInfoTemplate }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, - offsetof(CERTCertificate,issuerID), - SEC_ASN1_SUB(SEC_BitStringTemplate) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2, - offsetof(CERTCertificate,subjectID), - SEC_ASN1_SUB(SEC_BitStringTemplate) }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | - SEC_ASN1_CONTEXT_SPECIFIC | 3, - offsetof(CERTCertificate,extensions), - CERT_SequenceOfCertExtensionTemplate }, - { 0 } -}; - -const SEC_ASN1Template SEC_SignedCertificateTemplate[] = -{ - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTCertificate) }, - { SEC_ASN1_SAVE, - offsetof(CERTCertificate,signatureWrap.data) }, - { SEC_ASN1_INLINE, - 0, CERT_CertificateTemplate }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(CERTCertificate,signatureWrap.signatureAlgorithm), - SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, - { SEC_ASN1_BIT_STRING, - offsetof(CERTCertificate,signatureWrap.signature) }, - { 0 } -}; - -/* - * Find the subjectName in a DER encoded certificate - */ -const SEC_ASN1Template SEC_CertSubjectTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SECItem) }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | - SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, - 0, SEC_ASN1_SUB(SEC_SkipTemplate) }, /* version */ - { SEC_ASN1_SKIP }, /* serial number */ - { SEC_ASN1_SKIP }, /* signature algorithm */ - { SEC_ASN1_SKIP }, /* issuer */ - { SEC_ASN1_SKIP }, /* validity */ - { SEC_ASN1_ANY, 0, NULL }, /* subject */ - { SEC_ASN1_SKIP_REST }, - { 0 } -}; - -/* - * Find the issuerName in a DER encoded certificate - */ -const SEC_ASN1Template SEC_CertIssuerTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SECItem) }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | - SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, - 0, SEC_ASN1_SUB(SEC_SkipTemplate) }, /* version */ - { SEC_ASN1_SKIP }, /* serial number */ - { SEC_ASN1_SKIP }, /* signature algorithm */ - { SEC_ASN1_ANY, 0, NULL }, /* issuer */ - { SEC_ASN1_SKIP_REST }, - { 0 } -}; -/* - * Find the subjectName in a DER encoded certificate - */ -const SEC_ASN1Template SEC_CertSerialNumberTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SECItem) }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | - SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, - 0, SEC_ASN1_SUB(SEC_SkipTemplate) }, /* version */ - { SEC_ASN1_ANY, 0, NULL }, /* serial number */ - { SEC_ASN1_SKIP_REST }, - { 0 } -}; - -/* - * Find the issuer and serialNumber in a DER encoded certificate. - * This data is used as the database lookup key since its the unique - * identifier of a certificate. - */ -const SEC_ASN1Template CERT_CertKeyTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTCertKey) }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | - SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, - 0, SEC_ASN1_SUB(SEC_SkipTemplate) }, /* version */ - { SEC_ASN1_INTEGER, - offsetof(CERTCertKey,serialNumber) }, - { SEC_ASN1_SKIP }, /* signature algorithm */ - { SEC_ASN1_ANY, - offsetof(CERTCertKey,derIssuer) }, - { SEC_ASN1_SKIP_REST }, - { 0 } -}; - -SEC_ASN1_CHOOSER_IMPLEMENT(CERT_TimeChoiceTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CertificateTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SignedCertificateTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SequenceOfCertExtensionTemplate) - -SECStatus -CERT_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn, - SECItem *key) -{ - key->len = sn->len + issuer->len; - - if ((sn->data == NULL) || (issuer->data == NULL)) { - goto loser; - } - - key->data = (unsigned char*)PORT_ArenaAlloc(arena, key->len); - if ( !key->data ) { - goto loser; - } - - /* copy the serialNumber */ - PORT_Memcpy(key->data, sn->data, sn->len); - - /* copy the issuer */ - PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len); - - return(SECSuccess); - -loser: - return(SECFailure); -} - - -/* - * Extract the subject name from a DER certificate - */ -SECStatus -CERT_NameFromDERCert(SECItem *derCert, SECItem *derName) -{ - int rv; - PRArenaPool *arena; - CERTSignedData sd; - void *tmpptr; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - - if ( ! arena ) { - return(SECFailure); - } - - PORT_Memset(&sd, 0, sizeof(CERTSignedData)); - rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, derCert); - - if ( rv ) { - goto loser; - } - - PORT_Memset(derName, 0, sizeof(SECItem)); - rv = SEC_QuickDERDecodeItem(arena, derName, SEC_CertSubjectTemplate, &sd.data); - - if ( rv ) { - goto loser; - } - - tmpptr = derName->data; - derName->data = (unsigned char*)PORT_Alloc(derName->len); - if ( derName->data == NULL ) { - goto loser; - } - - PORT_Memcpy(derName->data, tmpptr, derName->len); - - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - PORT_FreeArena(arena, PR_FALSE); - return(SECFailure); -} - -SECStatus -CERT_IssuerNameFromDERCert(SECItem *derCert, SECItem *derName) -{ - int rv; - PRArenaPool *arena; - CERTSignedData sd; - void *tmpptr; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - - if ( ! arena ) { - return(SECFailure); - } - - PORT_Memset(&sd, 0, sizeof(CERTSignedData)); - rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, derCert); - - if ( rv ) { - goto loser; - } - - PORT_Memset(derName, 0, sizeof(SECItem)); - rv = SEC_QuickDERDecodeItem(arena, derName, SEC_CertIssuerTemplate, &sd.data); - - if ( rv ) { - goto loser; - } - - tmpptr = derName->data; - derName->data = (unsigned char*)PORT_Alloc(derName->len); - if ( derName->data == NULL ) { - goto loser; - } - - PORT_Memcpy(derName->data, tmpptr, derName->len); - - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - PORT_FreeArena(arena, PR_FALSE); - return(SECFailure); -} - -SECStatus -CERT_SerialNumberFromDERCert(SECItem *derCert, SECItem *derName) -{ - int rv; - PRArenaPool *arena; - CERTSignedData sd; - void *tmpptr; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - - if ( ! arena ) { - return(SECFailure); - } - - PORT_Memset(&sd, 0, sizeof(CERTSignedData)); - rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, derCert); - - if ( rv ) { - goto loser; - } - - PORT_Memset(derName, 0, sizeof(SECItem)); - rv = SEC_QuickDERDecodeItem(arena, derName, SEC_CertSerialNumberTemplate, &sd.data); - - if ( rv ) { - goto loser; - } - - tmpptr = derName->data; - derName->data = (unsigned char*)PORT_Alloc(derName->len); - if ( derName->data == NULL ) { - goto loser; - } - - PORT_Memcpy(derName->data, tmpptr, derName->len); - - PORT_FreeArena(arena, PR_FALSE); - return(SECSuccess); - -loser: - PORT_FreeArena(arena, PR_FALSE); - return(SECFailure); -} - -/* - * Generate a database key, based on serial number and issuer, from a - * DER certificate. - */ -SECStatus -CERT_KeyFromDERCert(PRArenaPool *reqArena, SECItem *derCert, SECItem *key) -{ - int rv; - CERTSignedData sd; - CERTCertKey certkey; - - if (!reqArena) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - PORT_Memset(&sd, 0, sizeof(CERTSignedData)); - rv = SEC_QuickDERDecodeItem(reqArena, &sd, CERT_SignedDataTemplate, - derCert); - - if ( rv ) { - goto loser; - } - - PORT_Memset(&certkey, 0, sizeof(CERTCertKey)); - rv = SEC_QuickDERDecodeItem(reqArena, &certkey, CERT_CertKeyTemplate, - &sd.data); - - if ( rv ) { - goto loser; - } - - return(CERT_KeyFromIssuerAndSN(reqArena, &certkey.derIssuer, - &certkey.serialNumber, key)); -loser: - return(SECFailure); -} - -/* - * fill in keyUsage field of the cert based on the cert extension - * if the extension is not critical, then we allow all uses - */ -static SECStatus -GetKeyUsage(CERTCertificate *cert) -{ - SECStatus rv; - SECItem tmpitem; - - rv = CERT_FindKeyUsageExtension(cert, &tmpitem); - if ( rv == SECSuccess ) { - /* remember the actual value of the extension */ - cert->rawKeyUsage = tmpitem.data[0]; - cert->keyUsagePresent = PR_TRUE; - cert->keyUsage = tmpitem.data[0]; - - PORT_Free(tmpitem.data); - tmpitem.data = NULL; - - } else { - /* if the extension is not present, then we allow all uses */ - cert->keyUsage = KU_ALL; - cert->rawKeyUsage = KU_ALL; - cert->keyUsagePresent = PR_FALSE; - } - - if ( CERT_GovtApprovedBitSet(cert) ) { - cert->keyUsage |= KU_NS_GOVT_APPROVED; - cert->rawKeyUsage |= KU_NS_GOVT_APPROVED; - } - - return(SECSuccess); -} - - -static SECStatus -findOIDinOIDSeqByTagNum(CERTOidSequence *seq, SECOidTag tagnum) -{ - SECItem **oids; - SECItem *oid; - SECStatus rv = SECFailure; - - if (seq != NULL) { - oids = seq->oids; - while (oids != NULL && *oids != NULL) { - oid = *oids; - if (SECOID_FindOIDTag(oid) == tagnum) { - rv = SECSuccess; - break; - } - oids++; - } - } - return rv; -} - -/* - * fill in nsCertType field of the cert based on the cert extension - */ -SECStatus -cert_GetCertType(CERTCertificate *cert) -{ - PRUint32 nsCertType; - - if (cert->nsCertType) { - /* once set, no need to recalculate */ - return SECSuccess; - } - nsCertType = cert_ComputeCertType(cert); - - /* Assert that it is safe to cast &cert->nsCertType to "PRInt32 *" */ - PORT_Assert(sizeof(cert->nsCertType) == sizeof(PRInt32)); - PR_ATOMIC_SET((PRInt32 *)&cert->nsCertType, nsCertType); - return SECSuccess; -} - -PRUint32 -cert_ComputeCertType(CERTCertificate *cert) -{ - SECStatus rv; - SECItem tmpitem; - SECItem encodedExtKeyUsage; - CERTOidSequence *extKeyUsage = NULL; - PRBool basicConstraintPresent = PR_FALSE; - CERTBasicConstraints basicConstraint; - PRUint32 nsCertType = 0; - - tmpitem.data = NULL; - CERT_FindNSCertTypeExtension(cert, &tmpitem); - encodedExtKeyUsage.data = NULL; - rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, - &encodedExtKeyUsage); - if (rv == SECSuccess) { - extKeyUsage = CERT_DecodeOidSequence(&encodedExtKeyUsage); - } - rv = CERT_FindBasicConstraintExten(cert, &basicConstraint); - if (rv == SECSuccess) { - basicConstraintPresent = PR_TRUE; - } - if (tmpitem.data != NULL || extKeyUsage != NULL) { - if (tmpitem.data == NULL) { - nsCertType = 0; - } else { - nsCertType = tmpitem.data[0]; - } - - /* free tmpitem data pointer to avoid memory leak */ - PORT_Free(tmpitem.data); - tmpitem.data = NULL; - - /* - * for this release, we will allow SSL certs with an email address - * to be used for email - */ - if ( ( nsCertType & NS_CERT_TYPE_SSL_CLIENT ) && - cert->emailAddr && cert->emailAddr[0]) { - nsCertType |= NS_CERT_TYPE_EMAIL; - } - /* - * for this release, we will allow SSL intermediate CAs to be - * email intermediate CAs too. - */ - if ( nsCertType & NS_CERT_TYPE_SSL_CA ) { - nsCertType |= NS_CERT_TYPE_EMAIL_CA; - } - /* - * allow a cert with the extended key usage of EMail Protect - * to be used for email or as an email CA, if basic constraints - * indicates that it is a CA. - */ - if (findOIDinOIDSeqByTagNum(extKeyUsage, - SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT) == - SECSuccess) { - if (basicConstraintPresent == PR_TRUE && - (basicConstraint.isCA)) { - nsCertType |= NS_CERT_TYPE_EMAIL_CA; - } else { - nsCertType |= NS_CERT_TYPE_EMAIL; - } - } - if (findOIDinOIDSeqByTagNum(extKeyUsage, - SEC_OID_EXT_KEY_USAGE_SERVER_AUTH) == - SECSuccess){ - if (basicConstraintPresent == PR_TRUE && - (basicConstraint.isCA)) { - nsCertType |= NS_CERT_TYPE_SSL_CA; - } else { - nsCertType |= NS_CERT_TYPE_SSL_SERVER; - } - } - /* - * Treat certs with step-up OID as also having SSL server type. - * COMODO needs this behaviour until June 2020. See Bug 737802. - */ - if (findOIDinOIDSeqByTagNum(extKeyUsage, - SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) == - SECSuccess){ - if (basicConstraintPresent == PR_TRUE && - (basicConstraint.isCA)) { - nsCertType |= NS_CERT_TYPE_SSL_CA; - } else { - nsCertType |= NS_CERT_TYPE_SSL_SERVER; - } - } - if (findOIDinOIDSeqByTagNum(extKeyUsage, - SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH) == - SECSuccess){ - if (basicConstraintPresent == PR_TRUE && - (basicConstraint.isCA)) { - nsCertType |= NS_CERT_TYPE_SSL_CA; - } else { - nsCertType |= NS_CERT_TYPE_SSL_CLIENT; - } - } - if (findOIDinOIDSeqByTagNum(extKeyUsage, - SEC_OID_EXT_KEY_USAGE_CODE_SIGN) == - SECSuccess) { - if (basicConstraintPresent == PR_TRUE && - (basicConstraint.isCA)) { - nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING_CA; - } else { - nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING; - } - } - if (findOIDinOIDSeqByTagNum(extKeyUsage, - SEC_OID_EXT_KEY_USAGE_TIME_STAMP) == - SECSuccess) { - nsCertType |= EXT_KEY_USAGE_TIME_STAMP; - } - if (findOIDinOIDSeqByTagNum(extKeyUsage, - SEC_OID_OCSP_RESPONDER) == - SECSuccess) { - nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER; - } - } else { - /* If no NS Cert Type extension and no EKU extension, then */ - nsCertType = 0; - if (CERT_IsCACert(cert, &nsCertType)) - nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER; - /* if the basic constraint extension says the cert is a CA, then - allow SSL CA and EMAIL CA and Status Responder */ - if (basicConstraintPresent && basicConstraint.isCA ) { - nsCertType |= (NS_CERT_TYPE_SSL_CA | - NS_CERT_TYPE_EMAIL_CA | - EXT_KEY_USAGE_STATUS_RESPONDER); - } - /* allow any ssl or email (no ca or object signing. */ - nsCertType |= NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_SSL_SERVER | - NS_CERT_TYPE_EMAIL; - } - - if (encodedExtKeyUsage.data != NULL) { - PORT_Free(encodedExtKeyUsage.data); - } - if (extKeyUsage != NULL) { - CERT_DestroyOidSequence(extKeyUsage); - } - return nsCertType; -} - -/* - * cert_GetKeyID() - extract or generate the subjectKeyID from a certificate - */ -SECStatus -cert_GetKeyID(CERTCertificate *cert) -{ - SECItem tmpitem; - SECStatus rv; - - cert->subjectKeyID.len = 0; - - /* see of the cert has a key identifier extension */ - rv = CERT_FindSubjectKeyIDExtension(cert, &tmpitem); - if ( rv == SECSuccess ) { - cert->subjectKeyID.data = (unsigned char*) PORT_ArenaAlloc(cert->arena, tmpitem.len); - if ( cert->subjectKeyID.data != NULL ) { - PORT_Memcpy(cert->subjectKeyID.data, tmpitem.data, tmpitem.len); - cert->subjectKeyID.len = tmpitem.len; - cert->keyIDGenerated = PR_FALSE; - } - - PORT_Free(tmpitem.data); - } - - /* if the cert doesn't have a key identifier extension, then generate one*/ - if ( cert->subjectKeyID.len == 0 ) { - /* - * pkix says that if the subjectKeyID is not present, then we should - * use the SHA-1 hash of the DER-encoded publicKeyInfo from the cert - */ - cert->subjectKeyID.data = (unsigned char *)PORT_ArenaAlloc(cert->arena, SHA1_LENGTH); - if ( cert->subjectKeyID.data != NULL ) { - rv = PK11_HashBuf(SEC_OID_SHA1,cert->subjectKeyID.data, - cert->derPublicKey.data, - cert->derPublicKey.len); - if ( rv == SECSuccess ) { - cert->subjectKeyID.len = SHA1_LENGTH; - } - } - } - - if ( cert->subjectKeyID.len == 0 ) { - return(SECFailure); - } - return(SECSuccess); - -} - -static PRBool -cert_IsRootCert(CERTCertificate *cert) -{ - SECStatus rv; - SECItem tmpitem; - - /* cache the authKeyID extension, if present */ - cert->authKeyID = CERT_FindAuthKeyIDExten(cert->arena, cert); - - /* it MUST be self-issued to be a root */ - if (cert->derIssuer.len == 0 || - !SECITEM_ItemsAreEqual(&cert->derIssuer, &cert->derSubject)) - { - return PR_FALSE; - } - - /* check the authKeyID extension */ - if (cert->authKeyID) { - /* authority key identifier is present */ - if (cert->authKeyID->keyID.len > 0) { - /* the keyIdentifier field is set, look for subjectKeyID */ - rv = CERT_FindSubjectKeyIDExtension(cert, &tmpitem); - if (rv == SECSuccess) { - PRBool match; - /* also present, they MUST match for it to be a root */ - match = SECITEM_ItemsAreEqual(&cert->authKeyID->keyID, - &tmpitem); - PORT_Free(tmpitem.data); - if (!match) return PR_FALSE; /* else fall through */ - } else { - /* the subject key ID is required when AKI is present */ - return PR_FALSE; - } - } - if (cert->authKeyID->authCertIssuer) { - SECItem *caName; - caName = (SECItem *)CERT_GetGeneralNameByType( - cert->authKeyID->authCertIssuer, - certDirectoryName, PR_TRUE); - if (caName) { - if (!SECITEM_ItemsAreEqual(&cert->derIssuer, caName)) { - return PR_FALSE; - } /* else fall through */ - } /* else ??? could not get general name as directory name? */ - } - if (cert->authKeyID->authCertSerialNumber.len > 0) { - if (!SECITEM_ItemsAreEqual(&cert->serialNumber, - &cert->authKeyID->authCertSerialNumber)) { - return PR_FALSE; - } /* else fall through */ - } - /* all of the AKI fields that were present passed the test */ - return PR_TRUE; - } - /* else the AKI was not present, so this is a root */ - return PR_TRUE; -} - -/* - * take a DER certificate and decode it into a certificate structure - */ -CERTCertificate * -CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, - char *nickname) -{ - CERTCertificate *cert; - PRArenaPool *arena; - void *data; - int rv; - int len; - char *tmpname; - - /* make a new arena */ - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - - if ( !arena ) { - return 0; - } - - /* allocate the certificate structure */ - cert = (CERTCertificate *)PORT_ArenaZAlloc(arena, sizeof(CERTCertificate)); - - if ( !cert ) { - goto loser; - } - - cert->arena = arena; - - if ( copyDER ) { - /* copy the DER data for the cert into this arena */ - data = (void *)PORT_ArenaAlloc(arena, derSignedCert->len); - if ( !data ) { - goto loser; - } - cert->derCert.data = (unsigned char *)data; - cert->derCert.len = derSignedCert->len; - PORT_Memcpy(data, derSignedCert->data, derSignedCert->len); - } else { - /* point to passed in DER data */ - cert->derCert = *derSignedCert; - } - - /* decode the certificate info */ - rv = SEC_QuickDERDecodeItem(arena, cert, SEC_SignedCertificateTemplate, - &cert->derCert); - - if ( rv ) { - goto loser; - } - - if (cert_HasUnknownCriticalExten (cert->extensions) == PR_TRUE) { - cert->options.bits.hasUnsupportedCriticalExt = PR_TRUE; - } - - /* generate and save the database key for the cert */ - rv = CERT_KeyFromIssuerAndSN(arena, &cert->derIssuer, &cert->serialNumber, - &cert->certKey); - if ( rv ) { - goto loser; - } - - /* set the nickname */ - if ( nickname == NULL ) { - cert->nickname = NULL; - } else { - /* copy and install the nickname */ - len = PORT_Strlen(nickname) + 1; - cert->nickname = (char*)PORT_ArenaAlloc(arena, len); - if ( cert->nickname == NULL ) { - goto loser; - } - - PORT_Memcpy(cert->nickname, nickname, len); - } - - /* set the email address */ - cert->emailAddr = cert_GetCertificateEmailAddresses(cert); - - /* initialize the subjectKeyID */ - rv = cert_GetKeyID(cert); - if ( rv != SECSuccess ) { - goto loser; - } - - /* initialize keyUsage */ - rv = GetKeyUsage(cert); - if ( rv != SECSuccess ) { - goto loser; - } - - /* determine if this is a root cert */ - cert->isRoot = cert_IsRootCert(cert); - - /* initialize the certType */ - rv = cert_GetCertType(cert); - if ( rv != SECSuccess ) { - goto loser; - } - - tmpname = CERT_NameToAscii(&cert->subject); - if ( tmpname != NULL ) { - cert->subjectName = PORT_ArenaStrdup(cert->arena, tmpname); - PORT_Free(tmpname); - } - - tmpname = CERT_NameToAscii(&cert->issuer); - if ( tmpname != NULL ) { - cert->issuerName = PORT_ArenaStrdup(cert->arena, tmpname); - PORT_Free(tmpname); - } - - cert->referenceCount = 1; - cert->slot = NULL; - cert->pkcs11ID = CK_INVALID_HANDLE; - cert->dbnickname = NULL; - - return(cert); - -loser: - - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(0); -} - -CERTCertificate * -__CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, - char *nickname) -{ - return CERT_DecodeDERCertificate(derSignedCert, copyDER, nickname); -} - - -CERTValidity * -CERT_CreateValidity(int64 notBefore, int64 notAfter) -{ - CERTValidity *v; - int rv; - PRArenaPool *arena; - - if (notBefore > notAfter) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - - if ( !arena ) { - return(0); - } - - v = (CERTValidity*) PORT_ArenaZAlloc(arena, sizeof(CERTValidity)); - if (v) { - v->arena = arena; - rv = DER_EncodeTimeChoice(arena, &v->notBefore, notBefore); - if (rv) goto loser; - rv = DER_EncodeTimeChoice(arena, &v->notAfter, notAfter); - if (rv) goto loser; - } - return v; - - loser: - CERT_DestroyValidity(v); - return 0; -} - -SECStatus -CERT_CopyValidity(PRArenaPool *arena, CERTValidity *to, CERTValidity *from) -{ - SECStatus rv; - - CERT_DestroyValidity(to); - to->arena = arena; - - rv = SECITEM_CopyItem(arena, &to->notBefore, &from->notBefore); - if (rv) return rv; - rv = SECITEM_CopyItem(arena, &to->notAfter, &from->notAfter); - return rv; -} - -void -CERT_DestroyValidity(CERTValidity *v) -{ - if (v && v->arena) { - PORT_FreeArena(v->arena, PR_FALSE); - } - return; -} - -/* -** Amount of time that a certifiate is allowed good before it is actually -** good. This is used for pending certificates, ones that are about to be -** valid. The slop is designed to allow for some variance in the clocks -** of the machine checking the certificate. -*/ -#define PENDING_SLOP (24L*60L*60L) /* seconds per day */ -static PRInt32 pendingSlop = PENDING_SLOP; /* seconds */ - -PRInt32 -CERT_GetSlopTime(void) -{ - return pendingSlop; /* seconds */ -} - -SECStatus -CERT_SetSlopTime(PRInt32 slop) /* seconds */ -{ - if (slop < 0) - return SECFailure; - pendingSlop = slop; - return SECSuccess; -} - -SECStatus -CERT_GetCertTimes(CERTCertificate *c, PRTime *notBefore, PRTime *notAfter) -{ - SECStatus rv; - - if (!c || !notBefore || !notAfter) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - /* convert DER not-before time */ - rv = DER_DecodeTimeChoice(notBefore, &c->validity.notBefore); - if (rv) { - return(SECFailure); - } - - /* convert DER not-after time */ - rv = DER_DecodeTimeChoice(notAfter, &c->validity.notAfter); - if (rv) { - return(SECFailure); - } - - return(SECSuccess); -} - -/* - * Check the validity times of a certificate - */ -SECCertTimeValidity -CERT_CheckCertValidTimes(CERTCertificate *c, PRTime t, PRBool allowOverride) -{ - PRTime notBefore, notAfter, llPendingSlop, tmp1; - SECStatus rv; - - if (!c) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return(secCertTimeUndetermined); - } - /* if cert is already marked OK, then don't bother to check */ - if ( allowOverride && c->timeOK ) { - return(secCertTimeValid); - } - - rv = CERT_GetCertTimes(c, ¬Before, ¬After); - - if (rv) { - return(secCertTimeExpired); /*XXX is this the right thing to do here?*/ - } - - LL_I2L(llPendingSlop, pendingSlop); - /* convert to micro seconds */ - LL_UI2L(tmp1, PR_USEC_PER_SEC); - LL_MUL(llPendingSlop, llPendingSlop, tmp1); - LL_SUB(notBefore, notBefore, llPendingSlop); - if ( LL_CMP( t, <, notBefore ) ) { - PORT_SetError(SEC_ERROR_EXPIRED_CERTIFICATE); - return(secCertTimeNotValidYet); - } - if ( LL_CMP( t, >, notAfter) ) { - PORT_SetError(SEC_ERROR_EXPIRED_CERTIFICATE); - return(secCertTimeExpired); - } - - return(secCertTimeValid); -} - -SECStatus -SEC_GetCrlTimes(CERTCrl *date, PRTime *notBefore, PRTime *notAfter) -{ - int rv; - - /* convert DER not-before time */ - rv = DER_DecodeTimeChoice(notBefore, &date->lastUpdate); - if (rv) { - return(SECFailure); - } - - /* convert DER not-after time */ - if (date->nextUpdate.data) { - rv = DER_DecodeTimeChoice(notAfter, &date->nextUpdate); - if (rv) { - return(SECFailure); - } - } - else { - LL_I2L(*notAfter, 0L); - } - return(SECSuccess); -} - -/* These routines should probably be combined with the cert - * routines using an common extraction routine. - */ -SECCertTimeValidity -SEC_CheckCrlTimes(CERTCrl *crl, PRTime t) { - PRTime notBefore, notAfter, llPendingSlop, tmp1; - SECStatus rv; - - rv = SEC_GetCrlTimes(crl, ¬Before, ¬After); - - if (rv) { - return(secCertTimeExpired); - } - - LL_I2L(llPendingSlop, pendingSlop); - /* convert to micro seconds */ - LL_I2L(tmp1, PR_USEC_PER_SEC); - LL_MUL(llPendingSlop, llPendingSlop, tmp1); - LL_SUB(notBefore, notBefore, llPendingSlop); - if ( LL_CMP( t, <, notBefore ) ) { - return(secCertTimeNotValidYet); - } - - /* If next update is omitted and the test for notBefore passes, then - we assume that the crl is up to date. - */ - if ( LL_IS_ZERO(notAfter) ) { - return(secCertTimeValid); - } - - if ( LL_CMP( t, >, notAfter) ) { - return(secCertTimeExpired); - } - - return(secCertTimeValid); -} - -PRBool -SEC_CrlIsNewer(CERTCrl *inNew, CERTCrl *old) { - PRTime newNotBefore, newNotAfter; - PRTime oldNotBefore, oldNotAfter; - SECStatus rv; - - /* problems with the new CRL? reject it */ - rv = SEC_GetCrlTimes(inNew, &newNotBefore, &newNotAfter); - if (rv) return PR_FALSE; - - /* problems with the old CRL? replace it */ - rv = SEC_GetCrlTimes(old, &oldNotBefore, &oldNotAfter); - if (rv) return PR_TRUE; - - /* Question: what about the notAfter's? */ - return ((PRBool)LL_CMP(oldNotBefore, <, newNotBefore)); -} - -/* - * return required key usage and cert type based on cert usage - */ -SECStatus -CERT_KeyUsageAndTypeForCertUsage(SECCertUsage usage, - PRBool ca, - unsigned int *retKeyUsage, - unsigned int *retCertType) -{ - unsigned int requiredKeyUsage = 0; - unsigned int requiredCertType = 0; - - if ( ca ) { - switch ( usage ) { - case certUsageSSLServerWithStepUp: - requiredKeyUsage = KU_NS_GOVT_APPROVED | KU_KEY_CERT_SIGN; - requiredCertType = NS_CERT_TYPE_SSL_CA; - break; - case certUsageSSLClient: - requiredKeyUsage = KU_KEY_CERT_SIGN; - requiredCertType = NS_CERT_TYPE_SSL_CA; - break; - case certUsageSSLServer: - requiredKeyUsage = KU_KEY_CERT_SIGN; - requiredCertType = NS_CERT_TYPE_SSL_CA; - break; - case certUsageSSLCA: - requiredKeyUsage = KU_KEY_CERT_SIGN; - requiredCertType = NS_CERT_TYPE_SSL_CA; - break; - case certUsageEmailSigner: - requiredKeyUsage = KU_KEY_CERT_SIGN; - requiredCertType = NS_CERT_TYPE_EMAIL_CA; - break; - case certUsageEmailRecipient: - requiredKeyUsage = KU_KEY_CERT_SIGN; - requiredCertType = NS_CERT_TYPE_EMAIL_CA; - break; - case certUsageObjectSigner: - requiredKeyUsage = KU_KEY_CERT_SIGN; - requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING_CA; - break; - case certUsageAnyCA: - case certUsageVerifyCA: - case certUsageStatusResponder: - requiredKeyUsage = KU_KEY_CERT_SIGN; - requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING_CA | - NS_CERT_TYPE_EMAIL_CA | - NS_CERT_TYPE_SSL_CA; - break; - default: - PORT_Assert(0); - goto loser; - } - } else { - switch ( usage ) { - case certUsageSSLClient: - /* - * RFC 5280 lists digitalSignature and keyAgreement for - * id-kp-clientAuth. NSS does not support the *_fixed_dh and - * *_fixed_ecdh client certificate types. - */ - requiredKeyUsage = KU_DIGITAL_SIGNATURE; - requiredCertType = NS_CERT_TYPE_SSL_CLIENT; - break; - case certUsageSSLServer: - requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT; - requiredCertType = NS_CERT_TYPE_SSL_SERVER; - break; - case certUsageSSLServerWithStepUp: - requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT | - KU_NS_GOVT_APPROVED; - requiredCertType = NS_CERT_TYPE_SSL_SERVER; - break; - case certUsageSSLCA: - requiredKeyUsage = KU_KEY_CERT_SIGN; - requiredCertType = NS_CERT_TYPE_SSL_CA; - break; - case certUsageEmailSigner: - requiredKeyUsage = KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION; - requiredCertType = NS_CERT_TYPE_EMAIL; - break; - case certUsageEmailRecipient: - requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT; - requiredCertType = NS_CERT_TYPE_EMAIL; - break; - case certUsageObjectSigner: - /* RFC 5280 lists only digitalSignature for id-kp-codeSigning. */ - requiredKeyUsage = KU_DIGITAL_SIGNATURE; - requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING; - break; - case certUsageStatusResponder: - requiredKeyUsage = KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION; - requiredCertType = EXT_KEY_USAGE_STATUS_RESPONDER; - break; - default: - PORT_Assert(0); - goto loser; - } - } - - if ( retKeyUsage != NULL ) { - *retKeyUsage = requiredKeyUsage; - } - if ( retCertType != NULL ) { - *retCertType = requiredCertType; - } - - return(SECSuccess); -loser: - return(SECFailure); -} - -/* - * check the key usage of a cert against a set of required values - */ -SECStatus -CERT_CheckKeyUsage(CERTCertificate *cert, unsigned int requiredUsage) -{ - if (!cert) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - /* choose between key agreement or key encipherment based on key - * type in cert - */ - if ( requiredUsage & KU_KEY_AGREEMENT_OR_ENCIPHERMENT ) { - KeyType keyType = CERT_GetCertKeyType(&cert->subjectPublicKeyInfo); - /* turn off the special bit */ - requiredUsage &= (~KU_KEY_AGREEMENT_OR_ENCIPHERMENT); - - switch (keyType) { - case rsaKey: - requiredUsage |= KU_KEY_ENCIPHERMENT; - break; - case dsaKey: - requiredUsage |= KU_DIGITAL_SIGNATURE; - break; - case dhKey: - requiredUsage |= KU_KEY_AGREEMENT; - break; - case ecKey: - /* Accept either signature or agreement. */ - if (!(cert->keyUsage & (KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT))) - goto loser; - break; - default: - goto loser; - } - } - - /* Allow either digital signature or non-repudiation */ - if ( requiredUsage & KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION ) { - /* turn off the special bit */ - requiredUsage &= (~KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION); - - if (!(cert->keyUsage & (KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION))) - goto loser; - } - - if ( (cert->keyUsage & requiredUsage) == requiredUsage ) - return SECSuccess; - -loser: - PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); - return SECFailure; -} - - -CERTCertificate * -CERT_DupCertificate(CERTCertificate *c) -{ - if (c) { - NSSCertificate *tmp = STAN_GetNSSCertificate(c); - nssCertificate_AddRef(tmp); - } - return c; -} - -/* - * Allow use of default cert database, so that apps(such as mozilla) don't - * have to pass the handle all over the place. - */ -static CERTCertDBHandle *default_cert_db_handle = 0; - -void -CERT_SetDefaultCertDB(CERTCertDBHandle *handle) -{ - default_cert_db_handle = handle; - - return; -} - -CERTCertDBHandle * -CERT_GetDefaultCertDB(void) -{ - return(default_cert_db_handle); -} - -/* XXX this would probably be okay/better as an xp routine? */ -static void -sec_lower_string(char *s) -{ - if ( s == NULL ) { - return; - } - - while ( *s ) { - *s = PORT_Tolower(*s); - s++; - } - - return; -} - -static PRBool -cert_IsIPAddr(const char *hn) -{ - PRBool isIPaddr = PR_FALSE; - PRNetAddr netAddr; - isIPaddr = (PR_SUCCESS == PR_StringToNetAddr(hn, &netAddr)); - return isIPaddr; -} - -/* -** Add a domain name to the list of names that the user has explicitly -** allowed (despite cert name mismatches) for use with a server cert. -*/ -SECStatus -CERT_AddOKDomainName(CERTCertificate *cert, const char *hn) -{ - CERTOKDomainName *domainOK; - int newNameLen; - - if (!hn || !(newNameLen = strlen(hn))) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - domainOK = (CERTOKDomainName *)PORT_ArenaZAlloc(cert->arena, - (sizeof *domainOK) + newNameLen); - if (!domainOK) - return SECFailure; /* error code is already set. */ - - PORT_Strcpy(domainOK->name, hn); - sec_lower_string(domainOK->name); - - /* put at head of list. */ - domainOK->next = cert->domainOK; - cert->domainOK = domainOK; - return SECSuccess; -} - -/* returns SECSuccess if hn matches pattern cn, -** returns SECFailure with SSL_ERROR_BAD_CERT_DOMAIN if no match, -** returns SECFailure with some other error code if another error occurs. -** -** This function may modify string cn, so caller must pass a modifiable copy. -*/ -static SECStatus -cert_TestHostName(char * cn, const char * hn) -{ - static int useShellExp = -1; - - if (useShellExp < 0) { - useShellExp = (NULL != PR_GetEnv("NSS_USE_SHEXP_IN_CERT_NAME")); - } - if (useShellExp) { - /* Backward compatible code, uses Shell Expressions (SHEXP). */ - int regvalid = PORT_RegExpValid(cn); - if (regvalid != NON_SXP) { - SECStatus rv; - /* cn is a regular expression, try to match the shexp */ - int match = PORT_RegExpCaseSearch(hn, cn); - - if ( match == 0 ) { - rv = SECSuccess; - } else { - PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN); - rv = SECFailure; - } - return rv; - } - } else { - /* New approach conforms to RFC 2818. */ - char *wildcard = PORT_Strchr(cn, '*'); - char *firstcndot = PORT_Strchr(cn, '.'); - char *secondcndot = firstcndot ? PORT_Strchr(firstcndot+1, '.') : NULL; - char *firsthndot = PORT_Strchr(hn, '.'); - - /* For a cn pattern to be considered valid, the wildcard character... - * - may occur only in a DNS name with at least 3 components, and - * - may occur only as last character in the first component, and - * - may be preceded by additional characters - */ - if (wildcard && secondcndot && secondcndot[1] && firsthndot - && firstcndot - wildcard == 1 - && secondcndot - firstcndot > 1 - && PORT_Strrchr(cn, '*') == wildcard - && !PORT_Strncasecmp(cn, hn, wildcard - cn) - && !PORT_Strcasecmp(firstcndot, firsthndot)) { - /* valid wildcard pattern match */ - return SECSuccess; - } - } - /* String cn has no wildcard or shell expression. - * Compare entire string hn with cert name. - */ - if (PORT_Strcasecmp(hn, cn) == 0) { - return SECSuccess; - } - - PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN); - return SECFailure; -} - - -SECStatus -cert_VerifySubjectAltName(CERTCertificate *cert, const char *hn) -{ - PRArenaPool * arena = NULL; - CERTGeneralName * nameList = NULL; - CERTGeneralName * current; - char * cn; - int cnBufLen; - unsigned int hnLen; - int DNSextCount = 0; - int IPextCount = 0; - PRBool isIPaddr = PR_FALSE; - SECStatus rv = SECFailure; - SECItem subAltName; - PRNetAddr netAddr; - char cnbuf[128]; - - subAltName.data = NULL; - hnLen = strlen(hn); - cn = cnbuf; - cnBufLen = sizeof cnbuf; - - rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME, - &subAltName); - if (rv != SECSuccess) { - goto fail; - } - isIPaddr = (PR_SUCCESS == PR_StringToNetAddr(hn, &netAddr)); - rv = SECFailure; - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (!arena) - goto fail; - - nameList = current = CERT_DecodeAltNameExtension(arena, &subAltName); - if (!current) - goto fail; - - do { - switch (current->type) { - case certDNSName: - if (!isIPaddr) { - /* DNS name current->name.other.data is not null terminated. - ** so must copy it. - */ - int cnLen = current->name.other.len; - rv = CERT_RFC1485_EscapeAndQuote(cn, cnBufLen, - (char *)current->name.other.data, - cnLen); - if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_OUTPUT_LEN) { - cnBufLen = cnLen * 3 + 3; /* big enough for worst case */ - cn = (char *)PORT_ArenaAlloc(arena, cnBufLen); - if (!cn) - goto fail; - rv = CERT_RFC1485_EscapeAndQuote(cn, cnBufLen, - (char *)current->name.other.data, - cnLen); - } - if (rv == SECSuccess) - rv = cert_TestHostName(cn ,hn); - if (rv == SECSuccess) - goto finish; - } - DNSextCount++; - break; - case certIPAddress: - if (isIPaddr) { - int match = 0; - PRIPv6Addr v6Addr; - if (current->name.other.len == 4 && /* IP v4 address */ - netAddr.inet.family == PR_AF_INET) { - match = !memcmp(&netAddr.inet.ip, - current->name.other.data, 4); - } else if (current->name.other.len == 16 && /* IP v6 address */ - netAddr.ipv6.family == PR_AF_INET6) { - match = !memcmp(&netAddr.ipv6.ip, - current->name.other.data, 16); - } else if (current->name.other.len == 16 && /* IP v6 address */ - netAddr.inet.family == PR_AF_INET) { - /* convert netAddr to ipv6, then compare. */ - /* ipv4 must be in Network Byte Order on input. */ - PR_ConvertIPv4AddrToIPv6(netAddr.inet.ip, &v6Addr); - match = !memcmp(&v6Addr, current->name.other.data, 16); - } else if (current->name.other.len == 4 && /* IP v4 address */ - netAddr.inet.family == PR_AF_INET6) { - /* convert netAddr to ipv6, then compare. */ - PRUint32 ipv4 = (current->name.other.data[0] << 24) | - (current->name.other.data[1] << 16) | - (current->name.other.data[2] << 8) | - current->name.other.data[3]; - /* ipv4 must be in Network Byte Order on input. */ - PR_ConvertIPv4AddrToIPv6(PR_htonl(ipv4), &v6Addr); - match = !memcmp(&netAddr.ipv6.ip, &v6Addr, 16); - } - if (match) { - rv = SECSuccess; - goto finish; - } - } - IPextCount++; - break; - default: - break; - } - current = CERT_GetNextGeneralName(current); - } while (current != nameList); - -fail: - - if (!(isIPaddr ? IPextCount : DNSextCount)) { - /* no relevant value in the extension was found. */ - PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND); - } else { - PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN); - } - rv = SECFailure; - -finish: - - /* Don't free nameList, it's part of the arena. */ - if (arena) { - PORT_FreeArena(arena, PR_FALSE); - } - - if (subAltName.data) { - SECITEM_FreeItem(&subAltName, PR_FALSE); - } - - return rv; -} - -/* - * If found: - * - subAltName contains the extension (caller must free) - * - return value is the decoded namelist (allocated off arena) - * if not found, or if failure to decode: - * - return value is NULL - */ -CERTGeneralName * -cert_GetSubjectAltNameList(CERTCertificate *cert, PRArenaPool *arena) -{ - CERTGeneralName * nameList = NULL; - SECStatus rv = SECFailure; - SECItem subAltName; - - if (!cert || !arena) - return NULL; - - subAltName.data = NULL; - - rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME, - &subAltName); - if (rv != SECSuccess) - return NULL; - - nameList = CERT_DecodeAltNameExtension(arena, &subAltName); - SECITEM_FreeItem(&subAltName, PR_FALSE); - return nameList; -} - -PRUint32 -cert_CountDNSPatterns(CERTGeneralName *firstName) -{ - CERTGeneralName * current; - PRUint32 count = 0; - - if (!firstName) - return 0; - - current = firstName; - do { - switch (current->type) { - case certDNSName: - case certIPAddress: - ++count; - break; - default: - break; - } - current = CERT_GetNextGeneralName(current); - } while (current != firstName); - - return count; -} - -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 46 -#endif - -/* will fill nickNames, - * will allocate all data from nickNames->arena, - * numberOfGeneralNames should have been obtained from cert_CountDNSPatterns, - * will ensure the numberOfGeneralNames matches the number of output entries. - */ -SECStatus -cert_GetDNSPatternsFromGeneralNames(CERTGeneralName *firstName, - PRUint32 numberOfGeneralNames, - CERTCertNicknames *nickNames) -{ - CERTGeneralName *currentInput; - char **currentOutput; - - if (!firstName || !nickNames || !numberOfGeneralNames) - return SECFailure; - - nickNames->numnicknames = numberOfGeneralNames; - nickNames->nicknames = PORT_ArenaAlloc(nickNames->arena, - sizeof(char *) * numberOfGeneralNames); - if (!nickNames->nicknames) - return SECFailure; - - currentInput = firstName; - currentOutput = nickNames->nicknames; - do { - char *cn = NULL; - char ipbuf[INET6_ADDRSTRLEN]; - PRNetAddr addr; - - if (numberOfGeneralNames < 1) { - /* internal consistency error */ - return SECFailure; - } - - switch (currentInput->type) { - case certDNSName: - /* DNS name currentInput->name.other.data is not null terminated. - ** so must copy it. - */ - cn = (char *)PORT_ArenaAlloc(nickNames->arena, - currentInput->name.other.len + 1); - if (!cn) - return SECFailure; - PORT_Memcpy(cn, currentInput->name.other.data, - currentInput->name.other.len); - cn[currentInput->name.other.len] = 0; - break; - case certIPAddress: - if (currentInput->name.other.len == 4) { - addr.inet.family = PR_AF_INET; - memcpy(&addr.inet.ip, currentInput->name.other.data, - currentInput->name.other.len); - } else if (currentInput->name.other.len == 16) { - addr.ipv6.family = PR_AF_INET6; - memcpy(&addr.ipv6.ip, currentInput->name.other.data, - currentInput->name.other.len); - } - if (PR_NetAddrToString(&addr, ipbuf, sizeof(ipbuf)) == PR_FAILURE) - return SECFailure; - cn = PORT_ArenaStrdup(nickNames->arena, ipbuf); - if (!cn) - return SECFailure; - break; - default: - break; - } - if (cn) { - *currentOutput = cn; - nickNames->totallen += PORT_Strlen(cn); - ++currentOutput; - --numberOfGeneralNames; - } - currentInput = CERT_GetNextGeneralName(currentInput); - } while (currentInput != firstName); - - return (numberOfGeneralNames == 0) ? SECSuccess : SECFailure; -} - -/* - * Collect all valid DNS names from the given cert. - * The output arena will reference some temporaray data, - * but this saves us from dealing with two arenas. - * The caller may free all data by freeing CERTCertNicknames->arena. - */ -CERTCertNicknames * -CERT_GetValidDNSPatternsFromCert(CERTCertificate *cert) -{ - CERTGeneralName *generalNames; - CERTCertNicknames *nickNames; - PRArenaPool *arena; - char *singleName; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (!arena) { - return NULL; - } - - nickNames = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames)); - if (!nickNames) { - PORT_FreeArena(arena, PR_FALSE); - return NULL; - } - - /* init the structure */ - nickNames->arena = arena; - nickNames->head = NULL; - nickNames->numnicknames = 0; - nickNames->nicknames = NULL; - nickNames->totallen = 0; - - generalNames = cert_GetSubjectAltNameList(cert, arena); - if (generalNames) { - SECStatus rv_getnames = SECFailure; - PRUint32 numNames = cert_CountDNSPatterns(generalNames); - - if (numNames) { - rv_getnames = cert_GetDNSPatternsFromGeneralNames(generalNames, - numNames, nickNames); - } - - /* if there were names, we'll exit now, either with success or failure */ - if (numNames) { - if (rv_getnames == SECSuccess) { - return nickNames; - } - - /* failure to produce output */ - PORT_FreeArena(arena, PR_FALSE); - return NULL; - } - } - - /* no SAN extension or no names found in extension */ - singleName = CERT_GetCommonName(&cert->subject); - if (singleName) { - nickNames->numnicknames = 1; - nickNames->nicknames = PORT_ArenaAlloc(arena, sizeof(char *)); - if (nickNames->nicknames) { - *nickNames->nicknames = PORT_ArenaStrdup(arena, singleName); - } - PORT_Free(singleName); - - /* Did we allocate both the buffer of pointers and the string? */ - if (nickNames->nicknames && *nickNames->nicknames) { - return nickNames; - } - } - - PORT_FreeArena(arena, PR_FALSE); - return NULL; -} - -/* Make sure that the name of the host we are connecting to matches the - * name that is incoded in the common-name component of the certificate - * that they are using. - */ -SECStatus -CERT_VerifyCertName(CERTCertificate *cert, const char *hn) -{ - char * cn; - SECStatus rv; - CERTOKDomainName *domainOK; - - if (!hn || !strlen(hn)) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - /* if the name is one that the user has already approved, it's OK. */ - for (domainOK = cert->domainOK; domainOK; domainOK = domainOK->next) { - if (0 == PORT_Strcasecmp(hn, domainOK->name)) { - return SECSuccess; - } - } - - /* Per RFC 2818, if the SubjectAltName extension is present, it must - ** be used as the cert's identity. - */ - rv = cert_VerifySubjectAltName(cert, hn); - if (rv == SECSuccess || PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) - return rv; - - cn = CERT_GetCommonName(&cert->subject); - if ( cn ) { - PRBool isIPaddr = cert_IsIPAddr(hn); - if (isIPaddr) { - if (PORT_Strcasecmp(hn, cn) == 0) { - rv = SECSuccess; - } else { - PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN); - rv = SECFailure; - } - } else { - rv = cert_TestHostName(cn, hn); - } - PORT_Free(cn); - } else - PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN); - return rv; -} - -PRBool -CERT_CompareCerts(CERTCertificate *c1, CERTCertificate *c2) -{ - SECComparison comp; - - comp = SECITEM_CompareItem(&c1->derCert, &c2->derCert); - if ( comp == SECEqual ) { /* certs are the same */ - return(PR_TRUE); - } else { - return(PR_FALSE); - } -} - -static SECStatus -StringsEqual(char *s1, char *s2) { - if ( ( s1 == NULL ) || ( s2 == NULL ) ) { - if ( s1 != s2 ) { /* only one is null */ - return(SECFailure); - } - return(SECSuccess); /* both are null */ - } - - if ( PORT_Strcmp( s1, s2 ) != 0 ) { - return(SECFailure); /* not equal */ - } - - return(SECSuccess); /* strings are equal */ -} - - -PRBool -CERT_CompareCertsForRedirection(CERTCertificate *c1, CERTCertificate *c2) -{ - SECComparison comp; - char *c1str, *c2str; - SECStatus eq; - - comp = SECITEM_CompareItem(&c1->derCert, &c2->derCert); - if ( comp == SECEqual ) { /* certs are the same */ - return(PR_TRUE); - } - - /* check if they are issued by the same CA */ - comp = SECITEM_CompareItem(&c1->derIssuer, &c2->derIssuer); - if ( comp != SECEqual ) { /* different issuer */ - return(PR_FALSE); - } - - /* check country name */ - c1str = CERT_GetCountryName(&c1->subject); - c2str = CERT_GetCountryName(&c2->subject); - eq = StringsEqual(c1str, c2str); - PORT_Free(c1str); - PORT_Free(c2str); - if ( eq != SECSuccess ) { - return(PR_FALSE); - } - - /* check locality name */ - c1str = CERT_GetLocalityName(&c1->subject); - c2str = CERT_GetLocalityName(&c2->subject); - eq = StringsEqual(c1str, c2str); - PORT_Free(c1str); - PORT_Free(c2str); - if ( eq != SECSuccess ) { - return(PR_FALSE); - } - - /* check state name */ - c1str = CERT_GetStateName(&c1->subject); - c2str = CERT_GetStateName(&c2->subject); - eq = StringsEqual(c1str, c2str); - PORT_Free(c1str); - PORT_Free(c2str); - if ( eq != SECSuccess ) { - return(PR_FALSE); - } - - /* check org name */ - c1str = CERT_GetOrgName(&c1->subject); - c2str = CERT_GetOrgName(&c2->subject); - eq = StringsEqual(c1str, c2str); - PORT_Free(c1str); - PORT_Free(c2str); - if ( eq != SECSuccess ) { - return(PR_FALSE); - } - -#ifdef NOTDEF - /* check orgUnit name */ - /* - * We need to revisit this and decide which fields should be allowed to be - * different - */ - c1str = CERT_GetOrgUnitName(&c1->subject); - c2str = CERT_GetOrgUnitName(&c2->subject); - eq = StringsEqual(c1str, c2str); - PORT_Free(c1str); - PORT_Free(c2str); - if ( eq != SECSuccess ) { - return(PR_FALSE); - } -#endif - - return(PR_TRUE); /* all fields but common name are the same */ -} - - -/* CERT_CertChainFromCert and CERT_DestroyCertificateList moved - to certhigh.c */ - - -CERTIssuerAndSN * -CERT_GetCertIssuerAndSN(PRArenaPool *arena, CERTCertificate *cert) -{ - CERTIssuerAndSN *result; - SECStatus rv; - - if ( arena == NULL ) { - arena = cert->arena; - } - - result = (CERTIssuerAndSN*)PORT_ArenaZAlloc(arena, sizeof(*result)); - if (result == NULL) { - PORT_SetError (SEC_ERROR_NO_MEMORY); - return NULL; - } - - rv = SECITEM_CopyItem(arena, &result->derIssuer, &cert->derIssuer); - if (rv != SECSuccess) - return NULL; - - rv = CERT_CopyName(arena, &result->issuer, &cert->issuer); - if (rv != SECSuccess) - return NULL; - - rv = SECITEM_CopyItem(arena, &result->serialNumber, &cert->serialNumber); - if (rv != SECSuccess) - return NULL; - - return result; -} - -char * -CERT_MakeCANickname(CERTCertificate *cert) -{ - char *firstname = NULL; - char *org = NULL; - char *nickname = NULL; - int count; - CERTCertificate *dummycert; - - firstname = CERT_GetCommonName(&cert->subject); - if ( firstname == NULL ) { - firstname = CERT_GetOrgUnitName(&cert->subject); - } - - org = CERT_GetOrgName(&cert->issuer); - if (org == NULL) { - org = CERT_GetDomainComponentName(&cert->issuer); - if (org == NULL) { - if (firstname) { - org = firstname; - firstname = NULL; - } else { - org = PORT_Strdup("Unknown CA"); - } - } - } - - /* can only fail if PORT_Strdup fails, in which case - * we're having memory problems. */ - if (org == NULL) { - goto done; - } - - - count = 1; - while ( 1 ) { - - if ( firstname ) { - if ( count == 1 ) { - nickname = PR_smprintf("%s - %s", firstname, org); - } else { - nickname = PR_smprintf("%s - %s #%d", firstname, org, count); - } - } else { - if ( count == 1 ) { - nickname = PR_smprintf("%s", org); - } else { - nickname = PR_smprintf("%s #%d", org, count); - } - } - if ( nickname == NULL ) { - goto done; - } - - /* look up the nickname to make sure it isn't in use already */ - dummycert = CERT_FindCertByNickname(cert->dbhandle, nickname); - - if ( dummycert == NULL ) { - goto done; - } - - /* found a cert, destroy it and loop */ - CERT_DestroyCertificate(dummycert); - - /* free the nickname */ - PORT_Free(nickname); - - count++; - } - -done: - if ( firstname ) { - PORT_Free(firstname); - } - if ( org ) { - PORT_Free(org); - } - - return(nickname); -} - -/* CERT_Import_CAChain moved to certhigh.c */ - -void -CERT_DestroyCrl (CERTSignedCrl *crl) -{ - SEC_DestroyCrl (crl); -} - -static int -cert_Version(CERTCertificate *cert) -{ - int version = 0; - if (cert && cert->version.data && cert->version.len) { - version = DER_GetInteger(&cert->version); - if (version < 0) - version = 0; - } - return version; -} - -static unsigned int -cert_ComputeTrustOverrides(CERTCertificate *cert, unsigned int cType) -{ - CERTCertTrust trust; - SECStatus rv = SECFailure; - - rv = CERT_GetCertTrust(cert, &trust); - - if (rv == SECSuccess && (trust.sslFlags | - trust.emailFlags | - trust.objectSigningFlags)) { - - if (trust.sslFlags & (CERTDB_TERMINAL_RECORD|CERTDB_TRUSTED)) - cType |= NS_CERT_TYPE_SSL_SERVER|NS_CERT_TYPE_SSL_CLIENT; - if (trust.sslFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED_CA)) - cType |= NS_CERT_TYPE_SSL_CA; -#if defined(CERTDB_NOT_TRUSTED) - if (trust.sslFlags & CERTDB_NOT_TRUSTED) - cType &= ~(NS_CERT_TYPE_SSL_SERVER|NS_CERT_TYPE_SSL_CLIENT| - NS_CERT_TYPE_SSL_CA); -#endif - if (trust.emailFlags & (CERTDB_TERMINAL_RECORD|CERTDB_TRUSTED)) - cType |= NS_CERT_TYPE_EMAIL; - if (trust.emailFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED_CA)) - cType |= NS_CERT_TYPE_EMAIL_CA; -#if defined(CERTDB_NOT_TRUSTED) - if (trust.emailFlags & CERTDB_NOT_TRUSTED) - cType &= ~(NS_CERT_TYPE_EMAIL|NS_CERT_TYPE_EMAIL_CA); -#endif - if (trust.objectSigningFlags & (CERTDB_TERMINAL_RECORD|CERTDB_TRUSTED)) - cType |= NS_CERT_TYPE_OBJECT_SIGNING; - if (trust.objectSigningFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED_CA)) - cType |= NS_CERT_TYPE_OBJECT_SIGNING_CA; -#if defined(CERTDB_NOT_TRUSTED) - if (trust.objectSigningFlags & CERTDB_NOT_TRUSTED) - cType &= ~(NS_CERT_TYPE_OBJECT_SIGNING| - NS_CERT_TYPE_OBJECT_SIGNING_CA); -#endif - } - return cType; -} - -/* - * Does a cert belong to a CA? We decide based on perm database trust - * flags, Netscape Cert Type Extension, and KeyUsage Extension. - */ -PRBool -CERT_IsCACert(CERTCertificate *cert, unsigned int *rettype) -{ - unsigned int cType = cert->nsCertType; - PRBool ret = PR_FALSE; - - if (cType & (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA | - NS_CERT_TYPE_OBJECT_SIGNING_CA)) { - ret = PR_TRUE; - } else { - SECStatus rv; - CERTBasicConstraints constraints; - - rv = CERT_FindBasicConstraintExten(cert, &constraints); - if (rv == SECSuccess && constraints.isCA) { - ret = PR_TRUE; - cType |= (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA); - } - } - - /* finally check if it's an X.509 v1 root CA */ - if (!ret && - (cert->isRoot && cert_Version(cert) < SEC_CERTIFICATE_VERSION_3)) { - ret = PR_TRUE; - cType |= (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA); - } - /* Now apply trust overrides, if any */ - cType = cert_ComputeTrustOverrides(cert, cType); - ret = (cType & (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA | - NS_CERT_TYPE_OBJECT_SIGNING_CA)) ? PR_TRUE : PR_FALSE; - - if (rettype != NULL) { - *rettype = cType; - } - return ret; -} - -PRBool -CERT_IsCADERCert(SECItem *derCert, unsigned int *type) { - CERTCertificate *cert; - PRBool isCA; - - /* This is okay -- only looks at extensions */ - cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); - if (cert == NULL) return PR_FALSE; - - isCA = CERT_IsCACert(cert,type); - CERT_DestroyCertificate (cert); - return isCA; -} - -PRBool -CERT_IsRootDERCert(SECItem *derCert) -{ - CERTCertificate *cert; - PRBool isRoot; - - /* This is okay -- only looks at extensions */ - cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); - if (cert == NULL) return PR_FALSE; - - isRoot = cert->isRoot; - CERT_DestroyCertificate (cert); - return isRoot; -} - -CERTCompareValidityStatus -CERT_CompareValidityTimes(CERTValidity* val_a, CERTValidity* val_b) -{ - PRTime notBeforeA, notBeforeB, notAfterA, notAfterB; - - if (!val_a || !val_b) - { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return certValidityUndetermined; - } - - if ( SECSuccess != DER_DecodeTimeChoice(¬BeforeA, &val_a->notBefore) || - SECSuccess != DER_DecodeTimeChoice(¬BeforeB, &val_b->notBefore) || - SECSuccess != DER_DecodeTimeChoice(¬AfterA, &val_a->notAfter) || - SECSuccess != DER_DecodeTimeChoice(¬AfterB, &val_b->notAfter) ) { - return certValidityUndetermined; - } - - /* sanity check */ - if (LL_CMP(notBeforeA,>,notAfterA) || LL_CMP(notBeforeB,>,notAfterB)) { - PORT_SetError(SEC_ERROR_INVALID_TIME); - return certValidityUndetermined; - } - - if (LL_CMP(notAfterA,!=,notAfterB)) { - /* one cert validity goes farther into the future, select it */ - return LL_CMP(notAfterA,<,notAfterB) ? - certValidityChooseB : certValidityChooseA; - } - /* the two certs have the same expiration date */ - PORT_Assert(LL_CMP(notAfterA, == , notAfterB)); - /* do they also have the same start date ? */ - if (LL_CMP(notBeforeA,==,notBeforeB)) { - return certValidityEqual; - } - /* choose cert with the later start date */ - return LL_CMP(notBeforeA,<,notBeforeB) ? - certValidityChooseB : certValidityChooseA; -} - -/* - * is certa newer than certb? If one is expired, pick the other one. - */ -PRBool -CERT_IsNewer(CERTCertificate *certa, CERTCertificate *certb) -{ - PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now; - SECStatus rv; - PRBool newerbefore, newerafter; - - rv = CERT_GetCertTimes(certa, ¬BeforeA, ¬AfterA); - if ( rv != SECSuccess ) { - return(PR_FALSE); - } - - rv = CERT_GetCertTimes(certb, ¬BeforeB, ¬AfterB); - if ( rv != SECSuccess ) { - return(PR_TRUE); - } - - newerbefore = PR_FALSE; - if ( LL_CMP(notBeforeA, >, notBeforeB) ) { - newerbefore = PR_TRUE; - } - - newerafter = PR_FALSE; - if ( LL_CMP(notAfterA, >, notAfterB) ) { - newerafter = PR_TRUE; - } - - if ( newerbefore && newerafter ) { - return(PR_TRUE); - } - - if ( ( !newerbefore ) && ( !newerafter ) ) { - return(PR_FALSE); - } - - /* get current time */ - now = PR_Now(); - - if ( newerbefore ) { - /* cert A was issued after cert B, but expires sooner */ - /* if A is expired, then pick B */ - if ( LL_CMP(notAfterA, <, now ) ) { - return(PR_FALSE); - } - return(PR_TRUE); - } else { - /* cert B was issued after cert A, but expires sooner */ - /* if B is expired, then pick A */ - if ( LL_CMP(notAfterB, <, now ) ) { - return(PR_TRUE); - } - return(PR_FALSE); - } -} - -void -CERT_DestroyCertArray(CERTCertificate **certs, unsigned int ncerts) -{ - unsigned int i; - - if ( certs ) { - for ( i = 0; i < ncerts; i++ ) { - if ( certs[i] ) { - CERT_DestroyCertificate(certs[i]); - } - } - - PORT_Free(certs); - } - - return; -} - -char * -CERT_FixupEmailAddr(const char *emailAddr) -{ - char *retaddr; - char *str; - - if ( emailAddr == NULL ) { - return(NULL); - } - - /* copy the string */ - str = retaddr = PORT_Strdup(emailAddr); - if ( str == NULL ) { - return(NULL); - } - - /* make it lower case */ - while ( *str ) { - *str = tolower( *str ); - str++; - } - - return(retaddr); -} - -/* - * NOTE - don't allow encode of govt-approved or invisible bits - */ -SECStatus -CERT_DecodeTrustString(CERTCertTrust *trust, const char *trusts) -{ - unsigned int i; - unsigned int *pflags; - - if (!trust) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - trust->sslFlags = 0; - trust->emailFlags = 0; - trust->objectSigningFlags = 0; - if (!trusts) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - pflags = &trust->sslFlags; - - for (i=0; i < PORT_Strlen(trusts); i++) { - switch (trusts[i]) { - case 'p': - *pflags = *pflags | CERTDB_TERMINAL_RECORD; - break; - - case 'P': - *pflags = *pflags | CERTDB_TRUSTED | CERTDB_TERMINAL_RECORD; - break; - - case 'w': - *pflags = *pflags | CERTDB_SEND_WARN; - break; - - case 'c': - *pflags = *pflags | CERTDB_VALID_CA; - break; - - case 'T': - *pflags = *pflags | CERTDB_TRUSTED_CLIENT_CA | CERTDB_VALID_CA; - break; - - case 'C' : - *pflags = *pflags | CERTDB_TRUSTED_CA | CERTDB_VALID_CA; - break; - - case 'u': - *pflags = *pflags | CERTDB_USER; - break; - - case 'i': - *pflags = *pflags | CERTDB_INVISIBLE_CA; - break; - case 'g': - *pflags = *pflags | CERTDB_GOVT_APPROVED_CA; - break; - - case ',': - if ( pflags == &trust->sslFlags ) { - pflags = &trust->emailFlags; - } else { - pflags = &trust->objectSigningFlags; - } - break; - default: - return SECFailure; - } - } - - return SECSuccess; -} - -static void -EncodeFlags(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; -} - -char * -CERT_EncodeTrustString(CERTCertTrust *trust) -{ - char tmpTrustSSL[32]; - char tmpTrustEmail[32]; - char tmpTrustSigning[32]; - char *retstr = NULL; - - if ( trust ) { - tmpTrustSSL[0] = '\0'; - tmpTrustEmail[0] = '\0'; - tmpTrustSigning[0] = '\0'; - - EncodeFlags(tmpTrustSSL, trust->sslFlags); - EncodeFlags(tmpTrustEmail, trust->emailFlags); - EncodeFlags(tmpTrustSigning, trust->objectSigningFlags); - - retstr = PR_smprintf("%s,%s,%s", tmpTrustSSL, tmpTrustEmail, - tmpTrustSigning); - } - - return(retstr); -} - -SECStatus -CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage, - unsigned int ncerts, SECItem **derCerts, - CERTCertificate ***retCerts, PRBool keepCerts, - PRBool caOnly, char *nickname) -{ - unsigned int i; - CERTCertificate **certs = NULL; - SECStatus rv; - unsigned int fcerts = 0; - - if ( ncerts ) { - certs = PORT_ZNewArray(CERTCertificate*, ncerts); - if ( certs == NULL ) { - return(SECFailure); - } - - /* decode all of the certs into the temporary DB */ - for ( i = 0, fcerts= 0; i < ncerts; i++) { - certs[fcerts] = CERT_NewTempCertificate(certdb, - derCerts[i], - NULL, - PR_FALSE, - PR_TRUE); - if (certs[fcerts]) { - SECItem subjKeyID = {siBuffer, NULL, 0}; - if (CERT_FindSubjectKeyIDExtension(certs[fcerts], - &subjKeyID) == SECSuccess) { - if (subjKeyID.data) { - cert_AddSubjectKeyIDMapping(&subjKeyID, certs[fcerts]); - } - SECITEM_FreeItem(&subjKeyID, PR_FALSE); - } - fcerts++; - } - } - - if ( keepCerts ) { - for ( i = 0; i < fcerts; i++ ) { - char* canickname = NULL; - PRBool isCA; - - SECKEY_UpdateCertPQG(certs[i]); - - isCA = CERT_IsCACert(certs[i], NULL); - if ( isCA ) { - canickname = CERT_MakeCANickname(certs[i]); - } - - if(isCA && (fcerts > 1)) { - /* if we are importing only a single cert and specifying - * a nickname, we want to use that nickname if it a CA, - * otherwise if there are more than one cert, we don't - * know which cert it belongs to. But we still may try - * the individual canickname from the cert itself. - */ - rv = CERT_AddTempCertToPerm(certs[i], canickname, NULL); - } else { - rv = CERT_AddTempCertToPerm(certs[i], - nickname?nickname:canickname, NULL); - } - - PORT_Free(canickname); - /* don't care if it fails - keep going */ - } - } - } - - if ( retCerts ) { - *retCerts = certs; - } else { - if (certs) { - CERT_DestroyCertArray(certs, fcerts); - } - } - - return ((fcerts || !ncerts) ? SECSuccess : SECFailure); -} - -/* - * a real list of certificates - need to convert CERTCertificateList - * stuff and ASN 1 encoder/decoder over to using this... - */ -CERTCertList * -CERT_NewCertList(void) -{ - PRArenaPool *arena = NULL; - CERTCertList *ret = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - ret = (CERTCertList *)PORT_ArenaZAlloc(arena, sizeof(CERTCertList)); - if ( ret == NULL ) { - goto loser; - } - - ret->arena = arena; - - PR_INIT_CLIST(&ret->list); - - return(ret); - -loser: - if ( arena != NULL ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -void -CERT_DestroyCertList(CERTCertList *certs) -{ - PRCList *node; - - while( !PR_CLIST_IS_EMPTY(&certs->list) ) { - node = PR_LIST_HEAD(&certs->list); - CERT_DestroyCertificate(((CERTCertListNode *)node)->cert); - PR_REMOVE_LINK(node); - } - - PORT_FreeArena(certs->arena, PR_FALSE); - - return; -} - -void -CERT_RemoveCertListNode(CERTCertListNode *node) -{ - CERT_DestroyCertificate(node->cert); - PR_REMOVE_LINK(&node->links); - return; -} - - -SECStatus -CERT_AddCertToListTailWithData(CERTCertList *certs, - CERTCertificate *cert, void *appData) -{ - CERTCertListNode *node; - - node = (CERTCertListNode *)PORT_ArenaZAlloc(certs->arena, - sizeof(CERTCertListNode)); - if ( node == NULL ) { - goto loser; - } - - PR_INSERT_BEFORE(&node->links, &certs->list); - /* certs->count++; */ - node->cert = cert; - node->appData = appData; - return(SECSuccess); - -loser: - return(SECFailure); -} - -SECStatus -CERT_AddCertToListTail(CERTCertList *certs, CERTCertificate *cert) -{ - return CERT_AddCertToListTailWithData(certs, cert, NULL); -} - -SECStatus -CERT_AddCertToListHeadWithData(CERTCertList *certs, - CERTCertificate *cert, void *appData) -{ - CERTCertListNode *node; - CERTCertListNode *head; - - head = CERT_LIST_HEAD(certs); - - if (head == NULL) return CERT_AddCertToListTail(certs,cert); - - node = (CERTCertListNode *)PORT_ArenaZAlloc(certs->arena, - sizeof(CERTCertListNode)); - if ( node == NULL ) { - goto loser; - } - - PR_INSERT_BEFORE(&node->links, &head->links); - /* certs->count++; */ - node->cert = cert; - node->appData = appData; - return(SECSuccess); - -loser: - return(SECFailure); -} - -SECStatus -CERT_AddCertToListHead(CERTCertList *certs, CERTCertificate *cert) -{ - return CERT_AddCertToListHeadWithData(certs, cert, NULL); -} - -/* - * Sort callback function to determine if cert a is newer than cert b. - * Not valid certs are considered older than valid certs. - */ -PRBool -CERT_SortCBValidity(CERTCertificate *certa, - CERTCertificate *certb, - void *arg) -{ - PRTime sorttime; - PRTime notBeforeA, notAfterA, notBeforeB, notAfterB; - SECStatus rv; - PRBool newerbefore, newerafter; - PRBool aNotValid = PR_FALSE, bNotValid = PR_FALSE; - - sorttime = *(PRTime *)arg; - - rv = CERT_GetCertTimes(certa, ¬BeforeA, ¬AfterA); - if ( rv != SECSuccess ) { - return(PR_FALSE); - } - - rv = CERT_GetCertTimes(certb, ¬BeforeB, ¬AfterB); - if ( rv != SECSuccess ) { - return(PR_TRUE); - } - newerbefore = PR_FALSE; - if ( LL_CMP(notBeforeA, >, notBeforeB) ) { - newerbefore = PR_TRUE; - } - newerafter = PR_FALSE; - if ( LL_CMP(notAfterA, >, notAfterB) ) { - newerafter = PR_TRUE; - } - - /* check if A is valid at sorttime */ - if ( CERT_CheckCertValidTimes(certa, sorttime, PR_FALSE) - != secCertTimeValid ) { - aNotValid = PR_TRUE; - } - - /* check if B is valid at sorttime */ - if ( CERT_CheckCertValidTimes(certb, sorttime, PR_FALSE) - != secCertTimeValid ) { - bNotValid = PR_TRUE; - } - - /* a is valid, b is not */ - if ( bNotValid && ( ! aNotValid ) ) { - return(PR_TRUE); - } - - /* b is valid, a is not */ - if ( aNotValid && ( ! bNotValid ) ) { - return(PR_FALSE); - } - - /* a and b are either valid or not valid */ - if ( newerbefore && newerafter ) { - return(PR_TRUE); - } - - if ( ( !newerbefore ) && ( !newerafter ) ) { - return(PR_FALSE); - } - - if ( newerbefore ) { - /* cert A was issued after cert B, but expires sooner */ - return(PR_TRUE); - } else { - /* cert B was issued after cert A, but expires sooner */ - return(PR_FALSE); - } -} - - -SECStatus -CERT_AddCertToListSorted(CERTCertList *certs, - CERTCertificate *cert, - CERTSortCallback f, - void *arg) -{ - CERTCertListNode *node; - CERTCertListNode *head; - PRBool ret; - - node = (CERTCertListNode *)PORT_ArenaZAlloc(certs->arena, - sizeof(CERTCertListNode)); - if ( node == NULL ) { - goto loser; - } - - head = CERT_LIST_HEAD(certs); - - while ( !CERT_LIST_END(head, certs) ) { - - /* if cert is already in the list, then don't add it again */ - if ( cert == head->cert ) { - /*XXX*/ - /* don't keep a reference */ - CERT_DestroyCertificate(cert); - goto done; - } - - ret = (* f)(cert, head->cert, arg); - /* if sort function succeeds, then insert before current node */ - if ( ret ) { - PR_INSERT_BEFORE(&node->links, &head->links); - goto done; - } - - head = CERT_LIST_NEXT(head); - } - /* if we get to the end, then just insert it at the tail */ - PR_INSERT_BEFORE(&node->links, &certs->list); - -done: - /* certs->count++; */ - node->cert = cert; - return(SECSuccess); - -loser: - return(SECFailure); -} - -/* This routine is here because pcertdb.c still has a call to it. - * The SMIME profile code in pcertdb.c should be split into high (find - * the email cert) and low (store the profile) code. At that point, we - * can move this to certhigh.c where it belongs. - * - * remove certs from a list that don't have keyUsage and certType - * that match the given usage. - */ -SECStatus -CERT_FilterCertListByUsage(CERTCertList *certList, SECCertUsage usage, - PRBool ca) -{ - unsigned int requiredKeyUsage; - unsigned int requiredCertType; - CERTCertListNode *node, *savenode; - SECStatus rv; - - if (certList == NULL) goto loser; - - rv = CERT_KeyUsageAndTypeForCertUsage(usage, ca, &requiredKeyUsage, - &requiredCertType); - if ( rv != SECSuccess ) { - goto loser; - } - - node = CERT_LIST_HEAD(certList); - - while ( !CERT_LIST_END(node, certList) ) { - - PRBool bad = (PRBool)(!node->cert); - - /* bad key usage ? */ - if ( !bad && - CERT_CheckKeyUsage(node->cert, requiredKeyUsage) != SECSuccess ) { - bad = PR_TRUE; - } - /* bad cert type ? */ - if ( !bad ) { - unsigned int certType = 0; - if ( ca ) { - /* This function returns a more comprehensive cert type that - * takes trust flags into consideration. Should probably - * fix the cert decoding code to do this. - */ - (void)CERT_IsCACert(node->cert, &certType); - } else { - certType = node->cert->nsCertType; - } - if ( !( certType & requiredCertType ) ) { - bad = PR_TRUE; - } - } - - if ( bad ) { - /* remove the node if it is bad */ - savenode = CERT_LIST_NEXT(node); - CERT_RemoveCertListNode(node); - node = savenode; - } else { - node = CERT_LIST_NEXT(node); - } - } - return(SECSuccess); - -loser: - return(SECFailure); -} - -PRBool CERT_IsUserCert(CERTCertificate* cert) -{ - CERTCertTrust trust; - SECStatus rv = SECFailure; - - rv = CERT_GetCertTrust(cert, &trust); - if (rv == SECSuccess && - ((trust.sslFlags & CERTDB_USER ) || - (trust.emailFlags & CERTDB_USER ) || - (trust.objectSigningFlags & CERTDB_USER )) ) { - return PR_TRUE; - } else { - return PR_FALSE; - } -} - -SECStatus -CERT_FilterCertListForUserCerts(CERTCertList *certList) -{ - CERTCertListNode *node, *freenode; - CERTCertificate *cert; - - if (!certList) { - return SECFailure; - } - - node = CERT_LIST_HEAD(certList); - - while ( ! CERT_LIST_END(node, certList) ) { - cert = node->cert; - if ( PR_TRUE != CERT_IsUserCert(cert) ) { - /* Not a User Cert, so remove this cert from the list */ - freenode = node; - node = CERT_LIST_NEXT(node); - CERT_RemoveCertListNode(freenode); - } else { - /* Is a User cert, so leave it in the list */ - node = CERT_LIST_NEXT(node); - } - } - - return(SECSuccess); -} - -static PZLock *certRefCountLock = NULL; - -/* - * Acquire the cert reference count lock - * There is currently one global lock for all certs, but I'm putting a cert - * arg here so that it will be easy to make it per-cert in the future if - * that turns out to be necessary. - */ -void -CERT_LockCertRefCount(CERTCertificate *cert) -{ - PORT_Assert(certRefCountLock != NULL); - PZ_Lock(certRefCountLock); - return; -} - -/* - * Free the cert reference count lock - */ -void -CERT_UnlockCertRefCount(CERTCertificate *cert) -{ - PRStatus prstat; - - PORT_Assert(certRefCountLock != NULL); - - prstat = PZ_Unlock(certRefCountLock); - - PORT_Assert(prstat == PR_SUCCESS); - - return; -} - -static PZLock *certTrustLock = NULL; - -/* - * Acquire the cert trust lock - * There is currently one global lock for all certs, but I'm putting a cert - * arg here so that it will be easy to make it per-cert in the future if - * that turns out to be necessary. - */ -void -CERT_LockCertTrust(CERTCertificate *cert) -{ - PORT_Assert(certTrustLock != NULL); - PZ_Lock(certTrustLock); - return; -} - -SECStatus -cert_InitLocks(void) -{ - if ( certRefCountLock == NULL ) { - certRefCountLock = PZ_NewLock(nssILockRefLock); - PORT_Assert(certRefCountLock != NULL); - if (!certRefCountLock) { - return SECFailure; - } - } - - if ( certTrustLock == NULL ) { - certTrustLock = PZ_NewLock(nssILockCertDB); - PORT_Assert(certTrustLock != NULL); - if (!certTrustLock) { - PZ_DestroyLock(certRefCountLock); - certRefCountLock = NULL; - return SECFailure; - } - } - - return SECSuccess; -} - -SECStatus -cert_DestroyLocks(void) -{ - SECStatus rv = SECSuccess; - - PORT_Assert(certRefCountLock != NULL); - if (certRefCountLock) { - PZ_DestroyLock(certRefCountLock); - certRefCountLock = NULL; - } else { - rv = SECFailure; - } - - PORT_Assert(certTrustLock != NULL); - if (certTrustLock) { - PZ_DestroyLock(certTrustLock); - certTrustLock = NULL; - } else { - rv = SECFailure; - } - return rv; -} - -/* - * Free the cert trust lock - */ -void -CERT_UnlockCertTrust(CERTCertificate *cert) -{ - PRStatus prstat; - - PORT_Assert(certTrustLock != NULL); - - prstat = PZ_Unlock(certTrustLock); - - PORT_Assert(prstat == PR_SUCCESS); - - return; -} - - -/* - * Get the StatusConfig data for this handle - */ -CERTStatusConfig * -CERT_GetStatusConfig(CERTCertDBHandle *handle) -{ - return handle->statusConfig; -} - -/* - * Set the StatusConfig data for this handle. There - * should not be another configuration set. - */ -void -CERT_SetStatusConfig(CERTCertDBHandle *handle, CERTStatusConfig *statusConfig) -{ - PORT_Assert(handle->statusConfig == NULL); - handle->statusConfig = statusConfig; -} - -/* - * Code for dealing with subjKeyID to cert mappings. - */ - -static PLHashTable *gSubjKeyIDHash = NULL; -static PRLock *gSubjKeyIDLock = NULL; -static PLHashTable *gSubjKeyIDSlotCheckHash = NULL; -static PRLock *gSubjKeyIDSlotCheckLock = NULL; - -static void *cert_AllocTable(void *pool, PRSize size) -{ - return PORT_Alloc(size); -} - -static void cert_FreeTable(void *pool, void *item) -{ - PORT_Free(item); -} - -static PLHashEntry* cert_AllocEntry(void *pool, const void *key) -{ - return PORT_New(PLHashEntry); -} - -static void cert_FreeEntry(void *pool, PLHashEntry *he, PRUintn flag) -{ - SECITEM_FreeItem((SECItem*)(he->value), PR_TRUE); - if (flag == HT_FREE_ENTRY) { - SECITEM_FreeItem((SECItem*)(he->key), PR_TRUE); - PORT_Free(he); - } -} - -static PLHashAllocOps cert_AllocOps = { - cert_AllocTable, cert_FreeTable, cert_AllocEntry, cert_FreeEntry -}; - -SECStatus -cert_CreateSubjectKeyIDSlotCheckHash(void) -{ - /* - * This hash is used to remember the series of a slot - * when we last checked for user certs - */ - gSubjKeyIDSlotCheckHash = PL_NewHashTable(0, SECITEM_Hash, - SECITEM_HashCompare, - SECITEM_HashCompare, - &cert_AllocOps, NULL); - if (!gSubjKeyIDSlotCheckHash) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - gSubjKeyIDSlotCheckLock = PR_NewLock(); - if (!gSubjKeyIDSlotCheckLock) { - PL_HashTableDestroy(gSubjKeyIDSlotCheckHash); - gSubjKeyIDSlotCheckHash = NULL; - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - return SECSuccess; -} - -SECStatus -cert_CreateSubjectKeyIDHashTable(void) -{ - gSubjKeyIDHash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, - SECITEM_HashCompare, - &cert_AllocOps, NULL); - if (!gSubjKeyIDHash) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - gSubjKeyIDLock = PR_NewLock(); - if (!gSubjKeyIDLock) { - PL_HashTableDestroy(gSubjKeyIDHash); - gSubjKeyIDHash = NULL; - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - /* initialize the companion hash (for remembering slot series) */ - if (cert_CreateSubjectKeyIDSlotCheckHash() != SECSuccess) { - cert_DestroySubjectKeyIDHashTable(); - return SECFailure; - } - return SECSuccess; -} - -SECStatus -cert_AddSubjectKeyIDMapping(SECItem *subjKeyID, CERTCertificate *cert) -{ - SECItem *newKeyID, *oldVal, *newVal; - SECStatus rv = SECFailure; - - if (!gSubjKeyIDLock) { - /* If one is created, then both are there. So only check for one. */ - return SECFailure; - } - - newVal = SECITEM_DupItem(&cert->derCert); - if (!newVal) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto done; - } - newKeyID = SECITEM_DupItem(subjKeyID); - if (!newKeyID) { - SECITEM_FreeItem(newVal, PR_TRUE); - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto done; - } - - PR_Lock(gSubjKeyIDLock); - /* The hash table implementation does not free up the memory - * associated with the key of an already existing entry if we add a - * duplicate, so we would wind up leaking the previously allocated - * key if we don't remove before adding. - */ - oldVal = (SECItem*)PL_HashTableLookup(gSubjKeyIDHash, subjKeyID); - if (oldVal) { - PL_HashTableRemove(gSubjKeyIDHash, subjKeyID); - } - - rv = (PL_HashTableAdd(gSubjKeyIDHash, newKeyID, newVal)) ? SECSuccess : - SECFailure; - PR_Unlock(gSubjKeyIDLock); -done: - return rv; -} - -SECStatus -cert_RemoveSubjectKeyIDMapping(SECItem *subjKeyID) -{ - SECStatus rv; - if (!gSubjKeyIDLock) - return SECFailure; - - PR_Lock(gSubjKeyIDLock); - rv = (PL_HashTableRemove(gSubjKeyIDHash, subjKeyID)) ? SECSuccess : - SECFailure; - PR_Unlock(gSubjKeyIDLock); - return rv; -} - -SECStatus -cert_UpdateSubjectKeyIDSlotCheck(SECItem *slotid, int series) -{ - SECItem *oldSeries, *newSlotid, *newSeries; - SECStatus rv = SECFailure; - - if (!gSubjKeyIDSlotCheckLock) { - return rv; - } - - newSlotid = SECITEM_DupItem(slotid); - newSeries = SECITEM_AllocItem(NULL, NULL, sizeof(int)); - if (!newSlotid || !newSeries ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - PORT_Memcpy(newSeries->data, &series, sizeof(int)); - - PR_Lock(gSubjKeyIDSlotCheckLock); - oldSeries = (SECItem *)PL_HashTableLookup(gSubjKeyIDSlotCheckHash, slotid); - if (oldSeries) { - /* - * make sure we don't leak the key of an existing entry - * (similar to cert_AddSubjectKeyIDMapping, see comment there) - */ - PL_HashTableRemove(gSubjKeyIDSlotCheckHash, slotid); - } - rv = (PL_HashTableAdd(gSubjKeyIDSlotCheckHash, newSlotid, newSeries)) ? - SECSuccess : SECFailure; - PR_Unlock(gSubjKeyIDSlotCheckLock); - if (rv == SECSuccess) { - return rv; - } - -loser: - if (newSlotid) { - SECITEM_FreeItem(newSlotid, PR_TRUE); - } - if (newSeries) { - SECITEM_FreeItem(newSeries, PR_TRUE); - } - return rv; -} - -int -cert_SubjectKeyIDSlotCheckSeries(SECItem *slotid) -{ - SECItem *seriesItem = NULL; - int series; - - if (!gSubjKeyIDSlotCheckLock) { - PORT_SetError(SEC_ERROR_NOT_INITIALIZED); - return -1; - } - - PR_Lock(gSubjKeyIDSlotCheckLock); - seriesItem = (SECItem *)PL_HashTableLookup(gSubjKeyIDSlotCheckHash, slotid); - PR_Unlock(gSubjKeyIDSlotCheckLock); - /* getting a null series just means we haven't registered one yet, - * just return 0 */ - if (seriesItem == NULL) { - return 0; - } - /* if we got a series back, assert if it's not the proper length. */ - PORT_Assert(seriesItem->len == sizeof(int)); - if (seriesItem->len != sizeof(int)) { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return -1; - } - PORT_Memcpy(&series, seriesItem->data, sizeof(int)); - return series; -} - -SECStatus -cert_DestroySubjectKeyIDSlotCheckHash(void) -{ - if (gSubjKeyIDSlotCheckHash) { - PR_Lock(gSubjKeyIDSlotCheckLock); - PL_HashTableDestroy(gSubjKeyIDSlotCheckHash); - gSubjKeyIDSlotCheckHash = NULL; - PR_Unlock(gSubjKeyIDSlotCheckLock); - PR_DestroyLock(gSubjKeyIDSlotCheckLock); - gSubjKeyIDSlotCheckLock = NULL; - } - return SECSuccess; -} - -SECStatus -cert_DestroySubjectKeyIDHashTable(void) -{ - if (gSubjKeyIDHash) { - PR_Lock(gSubjKeyIDLock); - PL_HashTableDestroy(gSubjKeyIDHash); - gSubjKeyIDHash = NULL; - PR_Unlock(gSubjKeyIDLock); - PR_DestroyLock(gSubjKeyIDLock); - gSubjKeyIDLock = NULL; - } - cert_DestroySubjectKeyIDSlotCheckHash(); - return SECSuccess; -} - -SECItem* -cert_FindDERCertBySubjectKeyID(SECItem *subjKeyID) -{ - SECItem *val; - - if (!gSubjKeyIDLock) - return NULL; - - PR_Lock(gSubjKeyIDLock); - val = (SECItem*)PL_HashTableLookup(gSubjKeyIDHash, subjKeyID); - if (val) { - val = SECITEM_DupItem(val); - } - PR_Unlock(gSubjKeyIDLock); - return val; -} - -CERTCertificate* -CERT_FindCertBySubjectKeyID(CERTCertDBHandle *handle, SECItem *subjKeyID) -{ - CERTCertificate *cert = NULL; - SECItem *derCert; - - derCert = cert_FindDERCertBySubjectKeyID(subjKeyID); - if (derCert) { - cert = CERT_FindCertByDERCert(handle, derCert); - SECITEM_FreeItem(derCert, PR_TRUE); - } - return cert; -} diff --git a/security/nss/lib/certdb/certdb.h b/security/nss/lib/certdb/certdb.h deleted file mode 100644 index 1c58f17be..000000000 --- a/security/nss/lib/certdb/certdb.h +++ /dev/null @@ -1,83 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.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 _CERTDB_H_ -#define _CERTDB_H_ - - -/* common flags for all types of certificates */ -#define CERTDB_TERMINAL_RECORD (1<<0) -#define CERTDB_TRUSTED (1<<1) -#define CERTDB_SEND_WARN (1<<2) -#define CERTDB_VALID_CA (1<<3) -#define CERTDB_TRUSTED_CA (1<<4) /* trusted for issuing server certs */ -#define CERTDB_NS_TRUSTED_CA (1<<5) -#define CERTDB_USER (1<<6) -#define CERTDB_TRUSTED_CLIENT_CA (1<<7) /* trusted for issuing client certs */ -#define CERTDB_INVISIBLE_CA (1<<8) /* don't show in UI */ -#define CERTDB_GOVT_APPROVED_CA (1<<9) /* can do strong crypto in export ver */ - -/* old usage, to keep old programs compiling */ -/* On Windows, Mac, and Linux (and other gcc platforms), we can give compile - * time deprecation warnings when applications use the old CERTDB_VALID_PEER - * define */ -#if __GNUC__ > 3 -#if (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) -typedef unsigned int __CERTDB_VALID_PEER __attribute__((deprecated)); -#else -typedef unsigned int __CERTDB_VALID_PEER __attribute__((deprecated - ("CERTDB_VALID_PEER is now CERTDB_TERMINAL_RECORD"))); -#endif -#define CERTDB_VALID_PEER ((__CERTDB_VALID_PEER) CERTDB_TERMINAL_RECORD) -#else -#ifdef _WIN32 -#pragma deprecated(CERTDB_VALID_PEER) -#endif -#define CERTDB_VALID_PEER CERTDB_TERMINAL_RECORD -#endif - -SEC_BEGIN_PROTOS - -CERTSignedCrl * -SEC_FindCrlByKey(CERTCertDBHandle *handle, SECItem *crlKey, int type); - -CERTSignedCrl * -SEC_FindCrlByName(CERTCertDBHandle *handle, SECItem *crlKey, int type); - -CERTSignedCrl * -SEC_FindCrlByDERCert(CERTCertDBHandle *handle, SECItem *derCrl, int type); - -PRBool -SEC_CertNicknameConflict(const char *nickname, SECItem *derSubject, - CERTCertDBHandle *handle); -CERTSignedCrl * -SEC_NewCrl(CERTCertDBHandle *handle, char *url, SECItem *derCrl, int type); - -SECStatus -SEC_DeletePermCRL(CERTSignedCrl *crl); - - -SECStatus -SEC_LookupCrls(CERTCertDBHandle *handle, CERTCrlHeadNode **nodes, int type); - -SECStatus -SEC_DestroyCrl(CERTSignedCrl *crl); - -CERTSignedCrl* SEC_DupCrl(CERTSignedCrl* acrl); - -SECStatus -CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, - CERTCertTrust *trust); - -SECStatus SEC_DeletePermCertificate(CERTCertificate *cert); - -PRBool -SEC_CrlIsNewer(CERTCrl *inNew, CERTCrl *old); - -SECCertTimeValidity -SEC_CheckCrlTimes(CERTCrl *crl, PRTime t); - -SEC_END_PROTOS - -#endif /* _CERTDB_H_ */ diff --git a/security/nss/lib/certdb/certi.h b/security/nss/lib/certdb/certi.h deleted file mode 100644 index 2b783ae37..000000000 --- a/security/nss/lib/certdb/certi.h +++ /dev/null @@ -1,383 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* - * certi.h - private data structures for the certificate library - * - * $Id$ - */ -#ifndef _CERTI_H_ -#define _CERTI_H_ - -#include "certt.h" -#include "nssrwlkt.h" - -/* -#define GLOBAL_RWLOCK 1 -*/ - -#define DPC_RWLOCK 1 - -/* all definitions in this file are subject to change */ - -typedef struct OpaqueCRLFieldsStr OpaqueCRLFields; -typedef struct CRLEntryCacheStr CRLEntryCache; -typedef struct CRLDPCacheStr CRLDPCache; -typedef struct CRLIssuerCacheStr CRLIssuerCache; -typedef struct CRLCacheStr CRLCache; -typedef struct CachedCrlStr CachedCrl; -typedef struct NamedCRLCacheStr NamedCRLCache; -typedef struct NamedCRLCacheEntryStr NamedCRLCacheEntry; - -struct OpaqueCRLFieldsStr { - PRBool partial; - PRBool decodingError; - PRBool badEntries; - PRBool badDER; - PRBool badExtensions; - PRBool heapDER; -}; - -typedef struct PreAllocatorStr PreAllocator; - -struct PreAllocatorStr -{ - PRSize len; - void* data; - PRSize used; - PRArenaPool* arena; - PRSize extra; -}; - -/* CRL entry cache. - This is the same as an entry plus the next/prev pointers for the hash table -*/ - -struct CRLEntryCacheStr { - CERTCrlEntry entry; - CRLEntryCache *prev, *next; -}; - -#define CRL_CACHE_INVALID_CRLS 0x0001 /* this state will be set - if we have CRL objects with an invalid DER or signature. Can be - cleared if the invalid objects are deleted from the token */ -#define CRL_CACHE_LAST_FETCH_FAILED 0x0002 /* this state will be set - if the last CRL fetch encountered an error. Can be cleared if a - new fetch succeeds */ - -#define CRL_CACHE_OUT_OF_MEMORY 0x0004 /* this state will be set - if we don't have enough memory to build the hash table of entries */ - -typedef enum { - CRL_OriginToken = 0, /* CRL came from PKCS#11 token */ - CRL_OriginExplicit = 1 /* CRL was explicitly added to the cache, from RAM */ -} CRLOrigin; - -typedef enum { - dpcacheNoEntry = 0, /* no entry found for this SN */ - dpcacheFoundEntry = 1, /* entry found for this SN */ - dpcacheCallerError = 2, /* invalid args */ - dpcacheInvalidCacheError = 3, /* CRL in cache may be bad DER */ - /* or unverified */ - dpcacheEmpty = 4, /* no CRL in cache */ - dpcacheLookupError = 5 /* internal error */ -} dpcacheStatus; - - -struct CachedCrlStr { - CERTSignedCrl* crl; - CRLOrigin origin; - /* hash table of entries. We use a PLHashTable and pre-allocate the - required amount of memory in one shot, so that our allocator can - simply pass offsets into it when hashing. - - This won't work anymore when we support delta CRLs and iCRLs, because - the size of the hash table will vary over time. At that point, the best - solution will be to allocate large CRLEntry structures by modifying - the DER decoding template. The extra space would be for next/prev - pointers. This would allow entries from different CRLs to be mixed in - the same hash table. - */ - PLHashTable* entries; - PreAllocator* prebuffer; /* big pre-allocated buffer mentioned above */ - PRBool sigChecked; /* this CRL signature has already been checked */ - PRBool sigValid; /* signature verification status . - Only meaningful if checked is PR_TRUE . */ - PRBool unbuildable; /* Avoid using assosiated CRL is it fails - * a decoding step */ -}; - -/* CRL distribution point cache object - This is a cache of CRL entries for a given distribution point of an issuer - It is built from a collection of one full and 0 or more delta CRLs. -*/ - -struct CRLDPCacheStr { -#ifdef DPC_RWLOCK - NSSRWLock* lock; -#else - PRLock* lock; -#endif - CERTCertificate* issuer; /* issuer cert - XXX there may be multiple issuer certs, - with different validity dates. Also - need to deal with SKID/AKID . See - bugzilla 217387, 233118 */ - SECItem* subject; /* DER of issuer subject */ - SECItem* distributionPoint; /* DER of distribution point. This may be - NULL when distribution points aren't - in use (ie. the CA has a single CRL). - Currently not used. */ - - /* array of full CRLs matching this distribution point */ - PRUint32 ncrls; /* total number of CRLs in crls */ - CachedCrl** crls; /* array of all matching CRLs */ - /* XCRL With iCRLs and multiple DPs, the CRL can be shared accross several - issuers. In the future, we'll need to globally recycle the CRL in a - separate list in order to avoid extra lookups, decodes, and copies */ - - /* pointers to good decoded CRLs used to build the cache */ - CachedCrl* selected; /* full CRL selected for use in the cache */ -#if 0 - /* for future use */ - PRInt32 numdeltas; /* number of delta CRLs used for the cache */ - CachedCrl** deltas; /* delta CRLs used for the cache */ -#endif - /* cache invalidity bitflag */ - PRUint16 invalid; /* this state will be set if either - CRL_CACHE_INVALID_CRLS or CRL_CACHE_LAST_FETCH_FAILED is set. - In those cases, all certs are considered to have unknown status. - The invalid state can only be cleared during an update if all - error states are cleared */ - PRBool refresh; /* manual refresh from tokens has been forced */ - PRBool mustchoose; /* trigger reselection algorithm, for case when - RAM CRL objects are dropped from the cache */ - PRTime lastfetch; /* time a CRL token fetch was last performed */ - PRTime lastcheck; /* time CRL token objects were last checked for - existence */ -}; - -/* CRL issuer cache object - This object tracks all the distribution point caches for a given issuer. - XCRL once we support multiple issuing distribution points, this object - will be a hash table. For now, it just holds the single CRL distribution - point cache structure. -*/ - -struct CRLIssuerCacheStr { - SECItem* subject; /* DER of issuer subject */ - CRLDPCache* dpp; -#if 0 - /* XCRL for future use. - We don't need to lock at the moment because we only have one DP, - which gets created at the same time as this object */ - NSSRWLock* lock; - CRLDPCache** dps; - PLHashTable* distributionpoints; - CERTCertificate* issuer; -#endif -}; - -/* CRL revocation cache object - This object tracks all the issuer caches -*/ - -struct CRLCacheStr { -#ifdef GLOBAL_RWLOCK - NSSRWLock* lock; -#else - PRLock* lock; -#endif - /* hash table of issuer to CRLIssuerCacheStr, - indexed by issuer DER subject */ - PLHashTable* issuers; -}; - -SECStatus InitCRLCache(void); -SECStatus ShutdownCRLCache(void); - -/* Returns a pointer to an environment-like string, a series of -** null-terminated strings, terminated by a zero-length string. -** This function is intended to be internal to NSS. -*/ -extern char * cert_GetCertificateEmailAddresses(CERTCertificate *cert); - -/* - * These functions are used to map subjectKeyID extension values to certs - * and to keep track of the checks for user certificates in each slot - */ -SECStatus -cert_CreateSubjectKeyIDHashTable(void); - -SECStatus -cert_AddSubjectKeyIDMapping(SECItem *subjKeyID, CERTCertificate *cert); - -SECStatus -cert_UpdateSubjectKeyIDSlotCheck(SECItem *slotid, int series); - -int -cert_SubjectKeyIDSlotCheckSeries(SECItem *slotid); - -/* - * Call this function to remove an entry from the mapping table. - */ -SECStatus -cert_RemoveSubjectKeyIDMapping(SECItem *subjKeyID); - -SECStatus -cert_DestroySubjectKeyIDHashTable(void); - -SECItem* -cert_FindDERCertBySubjectKeyID(SECItem *subjKeyID); - -/* return maximum length of AVA value based on its type OID tag. */ -extern int cert_AVAOidTagToMaxLen(SECOidTag tag); - -/* Make an AVA, allocated from pool, from OID and DER encoded value */ -extern CERTAVA * CERT_CreateAVAFromRaw(PRArenaPool *pool, - const SECItem * OID, const SECItem * value); - -/* Make an AVA from binary input specified by SECItem */ -extern CERTAVA * CERT_CreateAVAFromSECItem(PRArenaPool *arena, SECOidTag kind, - int valueType, SECItem *value); - -/* - * get a DPCache object for the given issuer subject and dp - * Automatically creates the cache object if it doesn't exist yet. - */ -SECStatus AcquireDPCache(CERTCertificate* issuer, const SECItem* subject, - const SECItem* dp, int64 t, void* wincx, - CRLDPCache** dpcache, PRBool* writeLocked); - -/* check if a particular SN is in the CRL cache and return its entry */ -dpcacheStatus DPCache_Lookup(CRLDPCache* cache, SECItem* sn, - CERTCrlEntry** returned); - -/* release a DPCache object that was previously acquired */ -void ReleaseDPCache(CRLDPCache* dpcache, PRBool writeLocked); - -/* - * map Stan errors into NSS errors - * This function examines the stan error stack and automatically sets - * PORT_SetError(); to the appropriate SEC_ERROR value. - */ -void CERT_MapStanError(); - -/* Interface function for libpkix cert validation engine: - * cert_verify wrapper. */ -SECStatus -cert_VerifyCertChainPkix(CERTCertificate *cert, - PRBool checkSig, - SECCertUsage requiredUsage, - PRTime time, - void *wincx, - CERTVerifyLog *log, - PRBool *sigError, - PRBool *revoked); - -SECStatus cert_InitLocks(void); - -SECStatus cert_DestroyLocks(void); - -/* - * fill in nsCertType field of the cert based on the cert extension - */ -extern SECStatus cert_GetCertType(CERTCertificate *cert); - -/* - * compute and return the value of nsCertType for cert, but do not - * update the CERTCertificate. - */ -extern PRUint32 cert_ComputeCertType(CERTCertificate *cert); - -void cert_AddToVerifyLog(CERTVerifyLog *log,CERTCertificate *cert, - long errorCode, unsigned int depth, - void *arg); - -/* Insert a DER CRL into the CRL cache, and take ownership of it. - * - * cert_CacheCRLByGeneralName takes ownership of the memory in crl argument - * completely. crl must be freeable by SECITEM_FreeItem. It will be freed - * immediately if it is rejected from the CRL cache, or later during cache - * updates when a new crl is available, or at shutdown time. - * - * canonicalizedName represents the source of the CRL, a GeneralName. - * The format of the encoding is not restricted, but all callers of - * cert_CacheCRLByGeneralName and cert_FindCRLByGeneralName must use - * the same encoding. To facilitate X.500 name matching, a canonicalized - * encoding of the GeneralName should be used, if available. - */ - -SECStatus cert_CacheCRLByGeneralName(CERTCertDBHandle* dbhandle, SECItem* crl, - const SECItem* canonicalizedName); - -struct NamedCRLCacheStr { - PRLock* lock; - PLHashTable* entries; -}; - -/* NamedCRLCacheEntryStr is filled in by cert_CacheCRLByGeneralName, - * and read by cert_FindCRLByGeneralName */ -struct NamedCRLCacheEntryStr { - SECItem* canonicalizedName; - SECItem* crl; /* DER, kept only if CRL - * is successfully cached */ - PRBool inCRLCache; - PRTime successfulInsertionTime; /* insertion time */ - PRTime lastAttemptTime; /* time of last call to - cert_CacheCRLByGeneralName with this name */ - PRBool badDER; /* ASN.1 error */ - PRBool dupe; /* matching DER CRL already in CRL cache */ - PRBool unsupported; /* IDP, delta, any other reason */ -}; - -typedef enum { - certRevocationStatusRevoked = 0, - certRevocationStatusValid = 1, - certRevocationStatusUnknown = 2 -} CERTRevocationStatus; - -/* Returns detailed status of the cert(revStatus variable). Tells if - * issuer cache has OriginFetchedWithTimeout crl in it. */ -SECStatus -cert_CheckCertRevocationStatus(CERTCertificate* cert, CERTCertificate* issuer, - const SECItem* dp, PRTime t, void *wincx, - CERTRevocationStatus *revStatus, - CERTCRLEntryReasonCode *revReason); - - -SECStatus cert_AcquireNamedCRLCache(NamedCRLCache** returned); - -/* cert_FindCRLByGeneralName must be called only while the named cache is - * acquired, and the entry is only valid until cache is released. - */ -SECStatus cert_FindCRLByGeneralName(NamedCRLCache* ncc, - const SECItem* canonicalizedName, - NamedCRLCacheEntry** retEntry); - -SECStatus cert_ReleaseNamedCRLCache(NamedCRLCache* ncc); - -/* This is private for now. Maybe shoule be public. */ -CERTGeneralName * -cert_GetSubjectAltNameList(CERTCertificate *cert, PRArenaPool *arena); - -/* Count DNS names and IP addresses in a list of GeneralNames */ -PRUint32 -cert_CountDNSPatterns(CERTGeneralName *firstName); - -/* - * returns the trust status of the leaf certificate based on usage. - * If the leaf is explicitly untrusted, this function will fail and - * failedFlags will be set to the trust bit value that lead to the failure. - * If the leaf is trusted, isTrusted is set to true and the function returns - * SECSuccess. This function does not check if the cert is fit for a - * particular usage. - */ -SECStatus -cert_CheckLeafTrust(CERTCertificate *cert, - SECCertUsage usage, - unsigned int *failedFlags, - PRBool *isTrusted); - -#endif /* _CERTI_H_ */ - diff --git a/security/nss/lib/certdb/certt.h b/security/nss/lib/certdb/certt.h deleted file mode 100644 index 681041b00..000000000 --- a/security/nss/lib/certdb/certt.h +++ /dev/null @@ -1,1345 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* - * certt.h - public data structures for the certificate library - * - * $Id$ - */ -#ifndef _CERTT_H_ -#define _CERTT_H_ - -#include "prclist.h" -#include "pkcs11t.h" -#include "seccomon.h" -#include "secmodt.h" -#include "secoidt.h" -#include "plarena.h" -#include "prcvar.h" -#include "nssilock.h" -#include "prio.h" -#include "prmon.h" - -/* Stan data types */ -struct NSSCertificateStr; -struct NSSTrustDomainStr; - -/* Non-opaque objects */ -typedef struct CERTAVAStr CERTAVA; -typedef struct CERTAttributeStr CERTAttribute; -typedef struct CERTAuthInfoAccessStr CERTAuthInfoAccess; -typedef struct CERTAuthKeyIDStr CERTAuthKeyID; -typedef struct CERTBasicConstraintsStr CERTBasicConstraints; -typedef struct NSSTrustDomainStr CERTCertDBHandle; -typedef struct CERTCertExtensionStr CERTCertExtension; -typedef struct CERTCertKeyStr CERTCertKey; -typedef struct CERTCertListStr CERTCertList; -typedef struct CERTCertListNodeStr CERTCertListNode; -typedef struct CERTCertNicknamesStr CERTCertNicknames; -typedef struct CERTCertTrustStr CERTCertTrust; -typedef struct CERTCertificateStr CERTCertificate; -typedef struct CERTCertificateListStr CERTCertificateList; -typedef struct CERTCertificateRequestStr CERTCertificateRequest; -typedef struct CERTCrlStr CERTCrl; -typedef struct CERTCrlDistributionPointsStr CERTCrlDistributionPoints; -typedef struct CERTCrlEntryStr CERTCrlEntry; -typedef struct CERTCrlHeadNodeStr CERTCrlHeadNode; -typedef struct CERTCrlKeyStr CERTCrlKey; -typedef struct CERTCrlNodeStr CERTCrlNode; -typedef struct CERTDERCertsStr CERTDERCerts; -typedef struct CERTDistNamesStr CERTDistNames; -typedef struct CERTGeneralNameStr CERTGeneralName; -typedef struct CERTGeneralNameListStr CERTGeneralNameList; -typedef struct CERTIssuerAndSNStr CERTIssuerAndSN; -typedef struct CERTNameStr CERTName; -typedef struct CERTNameConstraintStr CERTNameConstraint; -typedef struct CERTNameConstraintsStr CERTNameConstraints; -typedef struct CERTOKDomainNameStr CERTOKDomainName; -typedef struct CERTPrivKeyUsagePeriodStr CERTPrivKeyUsagePeriod; -typedef struct CERTPublicKeyAndChallengeStr CERTPublicKeyAndChallenge; -typedef struct CERTRDNStr CERTRDN; -typedef struct CERTSignedCrlStr CERTSignedCrl; -typedef struct CERTSignedDataStr CERTSignedData; -typedef struct CERTStatusConfigStr CERTStatusConfig; -typedef struct CERTSubjectListStr CERTSubjectList; -typedef struct CERTSubjectNodeStr CERTSubjectNode; -typedef struct CERTSubjectPublicKeyInfoStr CERTSubjectPublicKeyInfo; -typedef struct CERTValidityStr CERTValidity; -typedef struct CERTVerifyLogStr CERTVerifyLog; -typedef struct CERTVerifyLogNodeStr CERTVerifyLogNode; -typedef struct CRLDistributionPointStr CRLDistributionPoint; - -/* CRL extensions type */ -typedef unsigned long CERTCrlNumber; - -/* -** An X.500 AVA object -*/ -struct CERTAVAStr { - SECItem type; - SECItem value; -}; - -/* -** An X.500 RDN object -*/ -struct CERTRDNStr { - CERTAVA **avas; -}; - -/* -** An X.500 name object -*/ -struct CERTNameStr { - PLArenaPool *arena; - CERTRDN **rdns; -}; - -/* -** An X.509 validity object -*/ -struct CERTValidityStr { - PLArenaPool *arena; - SECItem notBefore; - SECItem notAfter; -}; - -/* - * A serial number and issuer name, which is used as a database key - */ -struct CERTCertKeyStr { - SECItem serialNumber; - SECItem derIssuer; -}; - -/* -** A signed data object. Used to implement the "signed" macro used -** in the X.500 specs. -*/ -struct CERTSignedDataStr { - SECItem data; - SECAlgorithmID signatureAlgorithm; - SECItem signature; -}; - -/* -** An X.509 subject-public-key-info object -*/ -struct CERTSubjectPublicKeyInfoStr { - PLArenaPool *arena; - SECAlgorithmID algorithm; - SECItem subjectPublicKey; -}; - -struct CERTPublicKeyAndChallengeStr { - SECItem spki; - SECItem challenge; -}; - -struct CERTCertTrustStr { - unsigned int sslFlags; - unsigned int emailFlags; - unsigned int objectSigningFlags; -}; - -/* - * defined the types of trust that exist - */ -typedef enum SECTrustTypeEnum { - trustSSL = 0, - trustEmail = 1, - trustObjectSigning = 2, - trustTypeNone = 3 -} SECTrustType; - -#define SEC_GET_TRUST_FLAGS(trust,type) \ - (((type)==trustSSL)?((trust)->sslFlags): \ - (((type)==trustEmail)?((trust)->emailFlags): \ - (((type)==trustObjectSigning)?((trust)->objectSigningFlags):0))) - -/* -** An X.509.3 certificate extension -*/ -struct CERTCertExtensionStr { - SECItem id; - SECItem critical; - SECItem value; -}; - -struct CERTSubjectNodeStr { - struct CERTSubjectNodeStr *next; - struct CERTSubjectNodeStr *prev; - SECItem certKey; - SECItem keyID; -}; - -struct CERTSubjectListStr { - PLArenaPool *arena; - int ncerts; - char *emailAddr; - CERTSubjectNode *head; - CERTSubjectNode *tail; /* do we need tail? */ - void *entry; -}; - -/* -** An X.509 certificate object (the unsigned form) -*/ -struct CERTCertificateStr { - /* the arena is used to allocate any data structures that have the same - * lifetime as the cert. This is all stuff that hangs off of the cert - * structure, and is all freed at the same time. I is used when the - * cert is decoded, destroyed, and at some times when it changes - * state - */ - PLArenaPool *arena; - - /* The following fields are static after the cert has been decoded */ - char *subjectName; - char *issuerName; - CERTSignedData signatureWrap; /* XXX */ - SECItem derCert; /* original DER for the cert */ - SECItem derIssuer; /* DER for issuer name */ - SECItem derSubject; /* DER for subject name */ - SECItem derPublicKey; /* DER for the public key */ - SECItem certKey; /* database key for this cert */ - SECItem version; - SECItem serialNumber; - SECAlgorithmID signature; - CERTName issuer; - CERTValidity validity; - CERTName subject; - CERTSubjectPublicKeyInfo subjectPublicKeyInfo; - SECItem issuerID; - SECItem subjectID; - CERTCertExtension **extensions; - char *emailAddr; - CERTCertDBHandle *dbhandle; - SECItem subjectKeyID; /* x509v3 subject key identifier */ - PRBool keyIDGenerated; /* was the keyid generated? */ - unsigned int keyUsage; /* what uses are allowed for this cert */ - unsigned int rawKeyUsage; /* value of the key usage extension */ - PRBool keyUsagePresent; /* was the key usage extension present */ - PRUint32 nsCertType; /* value of the ns cert type extension */ - /* must be 32-bit for PR_ATOMIC_SET */ - - /* these values can be set by the application to bypass certain checks - * or to keep the cert in memory for an entire session. - * XXX - need an api to set these - */ - PRBool keepSession; /* keep this cert for entire session*/ - PRBool timeOK; /* is the bad validity time ok? */ - CERTOKDomainName *domainOK; /* these domain names are ok */ - - /* - * these values can change when the cert changes state. These state - * changes include transitions from temp to perm or vice-versa, and - * changes of trust flags - */ - PRBool isperm; - PRBool istemp; - char *nickname; - char *dbnickname; - struct NSSCertificateStr *nssCertificate; /* This is Stan stuff. */ - CERTCertTrust *trust; - - /* the reference count is modified whenever someone looks up, dups - * or destroys a certificate - */ - int referenceCount; - - /* The subject list is a list of all certs with the same subject name. - * It can be modified any time a cert is added or deleted from either - * the in-memory(temporary) or on-disk(permanent) database. - */ - CERTSubjectList *subjectList; - - /* these belong in the static section, but are here to maintain - * the structure's integrity - */ - CERTAuthKeyID * authKeyID; /* x509v3 authority key identifier */ - PRBool isRoot; /* cert is the end of a chain */ - - /* these fields are used by client GUI code to keep track of ssl sockets - * that are blocked waiting on GUI feedback related to this cert. - * XXX - these should be moved into some sort of application specific - * data structure. They are only used by the browser right now. - */ - union { - void* apointer; /* was struct SECSocketNode* authsocketlist */ - struct { - unsigned int hasUnsupportedCriticalExt :1; - /* add any new option bits needed here */ - } bits; - } options; - int series; /* was int authsocketcount; record the series of the pkcs11ID */ - - /* This is PKCS #11 stuff. */ - PK11SlotInfo *slot; /*if this cert came of a token, which is it*/ - CK_OBJECT_HANDLE pkcs11ID; /*and which object on that token is it */ - PRBool ownSlot; /*true if the cert owns the slot reference */ -}; -#define SEC_CERTIFICATE_VERSION_1 0 /* default created */ -#define SEC_CERTIFICATE_VERSION_2 1 /* v2 */ -#define SEC_CERTIFICATE_VERSION_3 2 /* v3 extensions */ - -#define SEC_CRL_VERSION_1 0 /* default */ -#define SEC_CRL_VERSION_2 1 /* v2 extensions */ - -/* - * used to identify class of cert in mime stream code - */ -#define SEC_CERT_CLASS_CA 1 -#define SEC_CERT_CLASS_SERVER 2 -#define SEC_CERT_CLASS_USER 3 -#define SEC_CERT_CLASS_EMAIL 4 - -struct CERTDERCertsStr { - PLArenaPool *arena; - int numcerts; - SECItem *rawCerts; -}; - -/* -** A PKCS ? Attribute -** XXX this is duplicated through out the code, it *should* be moved -** to a central location. Where would be appropriate? -*/ -struct CERTAttributeStr { - SECItem attrType; - SECItem **attrValue; -}; - -/* -** A PKCS#10 certificate-request object (the unsigned form) -*/ -struct CERTCertificateRequestStr { - PLArenaPool *arena; - SECItem version; - CERTName subject; - CERTSubjectPublicKeyInfo subjectPublicKeyInfo; - CERTAttribute **attributes; -}; -#define SEC_CERTIFICATE_REQUEST_VERSION 0 /* what we *create* */ - - -/* -** A certificate list object. -*/ -struct CERTCertificateListStr { - SECItem *certs; - int len; /* number of certs */ - PLArenaPool *arena; -}; - -struct CERTCertListNodeStr { - PRCList links; - CERTCertificate *cert; - void *appData; -}; - -struct CERTCertListStr { - PRCList list; - PLArenaPool *arena; -}; - -#define CERT_LIST_HEAD(l) ((CERTCertListNode *)PR_LIST_HEAD(&l->list)) -#define CERT_LIST_NEXT(n) ((CERTCertListNode *)n->links.next) -#define CERT_LIST_END(n,l) (((void *)n) == ((void *)&l->list)) -#define CERT_LIST_EMPTY(l) CERT_LIST_END(CERT_LIST_HEAD(l), l) - -struct CERTCrlEntryStr { - SECItem serialNumber; - SECItem revocationDate; - CERTCertExtension **extensions; -}; - -struct CERTCrlStr { - PLArenaPool *arena; - SECItem version; - SECAlgorithmID signatureAlg; - SECItem derName; - CERTName name; - SECItem lastUpdate; - SECItem nextUpdate; /* optional for x.509 CRL */ - CERTCrlEntry **entries; - CERTCertExtension **extensions; - /* can't add anything there for binary backwards compatibility reasons */ -}; - -struct CERTCrlKeyStr { - SECItem derName; - SECItem dummy; /* The decoder can not skip a primitive, - this serves as a place holder for the - decoder to finish its task only - */ -}; - -struct CERTSignedCrlStr { - PLArenaPool *arena; - CERTCrl crl; - void *reserved1; - PRBool reserved2; - PRBool isperm; - PRBool istemp; - int referenceCount; - CERTCertDBHandle *dbhandle; - CERTSignedData signatureWrap; /* XXX */ - char *url; - SECItem *derCrl; - PK11SlotInfo *slot; - CK_OBJECT_HANDLE pkcs11ID; - void* opaque; /* do not touch */ -}; - - -struct CERTCrlHeadNodeStr { - PLArenaPool *arena; - CERTCertDBHandle *dbhandle; - CERTCrlNode *first; - CERTCrlNode *last; -}; - - -struct CERTCrlNodeStr { - CERTCrlNode *next; - int type; - CERTSignedCrl *crl; -}; - - -/* - * Array of X.500 Distinguished Names - */ -struct CERTDistNamesStr { - PLArenaPool *arena; - int nnames; - SECItem *names; - void *head; /* private */ -}; - - -#define NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ -#define NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ -#define NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ -#define NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ -#define NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ -#define NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ -#define NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ -#define NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ - -#define EXT_KEY_USAGE_TIME_STAMP (0x8000) -#define EXT_KEY_USAGE_STATUS_RESPONDER (0x4000) - -#define NS_CERT_TYPE_APP ( NS_CERT_TYPE_SSL_CLIENT | \ - NS_CERT_TYPE_SSL_SERVER | \ - NS_CERT_TYPE_EMAIL | \ - NS_CERT_TYPE_OBJECT_SIGNING ) - -#define NS_CERT_TYPE_CA ( NS_CERT_TYPE_SSL_CA | \ - NS_CERT_TYPE_EMAIL_CA | \ - NS_CERT_TYPE_OBJECT_SIGNING_CA | \ - EXT_KEY_USAGE_STATUS_RESPONDER ) -typedef enum SECCertUsageEnum { - certUsageSSLClient = 0, - certUsageSSLServer = 1, - certUsageSSLServerWithStepUp = 2, - certUsageSSLCA = 3, - certUsageEmailSigner = 4, - certUsageEmailRecipient = 5, - certUsageObjectSigner = 6, - certUsageUserCertImport = 7, - certUsageVerifyCA = 8, - certUsageProtectedObjectSigner = 9, - certUsageStatusResponder = 10, - certUsageAnyCA = 11 -} SECCertUsage; - -typedef PRInt64 SECCertificateUsage; - -#define certificateUsageCheckAllUsages (0x0000) -#define certificateUsageSSLClient (0x0001) -#define certificateUsageSSLServer (0x0002) -#define certificateUsageSSLServerWithStepUp (0x0004) -#define certificateUsageSSLCA (0x0008) -#define certificateUsageEmailSigner (0x0010) -#define certificateUsageEmailRecipient (0x0020) -#define certificateUsageObjectSigner (0x0040) -#define certificateUsageUserCertImport (0x0080) -#define certificateUsageVerifyCA (0x0100) -#define certificateUsageProtectedObjectSigner (0x0200) -#define certificateUsageStatusResponder (0x0400) -#define certificateUsageAnyCA (0x0800) - -#define certificateUsageHighest certificateUsageAnyCA - -/* - * Does the cert belong to the user, a peer, or a CA. - */ -typedef enum CERTCertOwnerEnum { - certOwnerUser = 0, - certOwnerPeer = 1, - certOwnerCA = 2 -} CERTCertOwner; - -/* - * This enum represents the state of validity times of a certificate - */ -typedef enum SECCertTimeValidityEnum { - secCertTimeValid = 0, - secCertTimeExpired = 1, - secCertTimeNotValidYet = 2, - secCertTimeUndetermined = 3 /* validity could not be decoded from the - cert, most likely because it was NULL */ -} SECCertTimeValidity; - -/* - * This is used as return status in functions that compare the validity - * periods of two certificates A and B, currently only - * CERT_CompareValidityTimes. - */ - -typedef enum CERTCompareValidityStatusEnum -{ - certValidityUndetermined = 0, /* the function is unable to select one cert - over another */ - certValidityChooseB = 1, /* cert B should be preferred */ - certValidityEqual = 2, /* both certs have the same validity period */ - certValidityChooseA = 3 /* cert A should be preferred */ -} CERTCompareValidityStatus; - -/* - * Interface for getting certificate nickname strings out of the database - */ - -/* these are values for the what argument below */ -#define SEC_CERT_NICKNAMES_ALL 1 -#define SEC_CERT_NICKNAMES_USER 2 -#define SEC_CERT_NICKNAMES_SERVER 3 -#define SEC_CERT_NICKNAMES_CA 4 - -struct CERTCertNicknamesStr { - PLArenaPool *arena; - void *head; - int numnicknames; - char **nicknames; - int what; - int totallen; -}; - -struct CERTIssuerAndSNStr { - SECItem derIssuer; - CERTName issuer; - SECItem serialNumber; -}; - - -/* X.509 v3 Key Usage Extension flags */ -#define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ -#define KU_NON_REPUDIATION (0x40) /* bit 1 */ -#define KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ -#define KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ -#define KU_KEY_AGREEMENT (0x08) /* bit 4 */ -#define KU_KEY_CERT_SIGN (0x04) /* bit 5 */ -#define KU_CRL_SIGN (0x02) /* bit 6 */ -#define KU_ENCIPHER_ONLY (0x01) /* bit 7 */ -#define KU_ALL (KU_DIGITAL_SIGNATURE | \ - KU_NON_REPUDIATION | \ - KU_KEY_ENCIPHERMENT | \ - KU_DATA_ENCIPHERMENT | \ - KU_KEY_AGREEMENT | \ - KU_KEY_CERT_SIGN | \ - KU_CRL_SIGN | \ - KU_ENCIPHER_ONLY) - -/* This value will not occur in certs. It is used internally for the case - * when either digital signature or non-repudiation is the correct value. - */ -#define KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION (0x2000) - -/* This value will not occur in certs. It is used internally for the case - * when the key type is not know ahead of time and either key agreement or - * key encipherment are the correct value based on key type - */ -#define KU_KEY_AGREEMENT_OR_ENCIPHERMENT (0x4000) - -/* internal bits that do not match bits in the x509v3 spec, but are used - * for similar purposes - */ -#define KU_NS_GOVT_APPROVED (0x8000) /*don't make part of KU_ALL!*/ -/* - * x.509 v3 Basic Constraints Extension - * If isCA is false, the pathLenConstraint is ignored. - * Otherwise, the following pathLenConstraint values will apply: - * < 0 - there is no limit to the certificate path - * 0 - CA can issues end-entity certificates only - * > 0 - the number of certificates in the certificate path is - * limited to this number - */ -#define CERT_UNLIMITED_PATH_CONSTRAINT -2 - -struct CERTBasicConstraintsStr { - PRBool isCA; /* on if is CA */ - int pathLenConstraint; /* maximum number of certificates that can be - in the cert path. Only applies to a CA - certificate; otherwise, it's ignored. - */ -}; - -/* Maximum length of a certificate chain */ -#define CERT_MAX_CERT_CHAIN 20 - -#define CERT_MAX_SERIAL_NUMBER_BYTES 20 /* from RFC 3280 */ -#define CERT_MAX_DN_BYTES 4096 /* arbitrary */ - -/* x.509 v3 Reason Flags, used in CRLDistributionPoint Extension */ -#define RF_UNUSED (0x80) /* bit 0 */ -#define RF_KEY_COMPROMISE (0x40) /* bit 1 */ -#define RF_CA_COMPROMISE (0x20) /* bit 2 */ -#define RF_AFFILIATION_CHANGED (0x10) /* bit 3 */ -#define RF_SUPERSEDED (0x08) /* bit 4 */ -#define RF_CESSATION_OF_OPERATION (0x04) /* bit 5 */ -#define RF_CERTIFICATE_HOLD (0x02) /* bit 6 */ - -/* enum for CRL Entry Reason Code */ -typedef enum CERTCRLEntryReasonCodeEnum { - crlEntryReasonUnspecified = 0, - crlEntryReasonKeyCompromise = 1, - crlEntryReasonCaCompromise = 2, - crlEntryReasonAffiliationChanged = 3, - crlEntryReasonSuperseded = 4, - crlEntryReasonCessationOfOperation = 5, - crlEntryReasoncertificatedHold = 6, - crlEntryReasonRemoveFromCRL = 8, - crlEntryReasonPrivilegeWithdrawn = 9, - crlEntryReasonAaCompromise = 10 -} CERTCRLEntryReasonCode; - -/* If we needed to extract the general name field, use this */ -/* General Name types */ -typedef enum CERTGeneralNameTypeEnum { - certOtherName = 1, - certRFC822Name = 2, - certDNSName = 3, - certX400Address = 4, - certDirectoryName = 5, - certEDIPartyName = 6, - certURI = 7, - certIPAddress = 8, - certRegisterID = 9 -} CERTGeneralNameType; - - -typedef struct OtherNameStr { - SECItem name; - SECItem oid; -}OtherName; - - - -struct CERTGeneralNameStr { - CERTGeneralNameType type; /* name type */ - union { - CERTName directoryName; /* distinguish name */ - OtherName OthName; /* Other Name */ - SECItem other; /* the rest of the name forms */ - }name; - SECItem derDirectoryName; /* this is saved to simplify directory name - comparison */ - PRCList l; -}; - -struct CERTGeneralNameListStr { - PLArenaPool *arena; - CERTGeneralName *name; - int refCount; - int len; - PZLock *lock; -}; - -struct CERTNameConstraintStr { - CERTGeneralName name; - SECItem DERName; - SECItem min; - SECItem max; - PRCList l; -}; - - -struct CERTNameConstraintsStr { - CERTNameConstraint *permited; - CERTNameConstraint *excluded; - SECItem **DERPermited; - SECItem **DERExcluded; -}; - - -/* Private Key Usage Period extension struct. */ -struct CERTPrivKeyUsagePeriodStr { - SECItem notBefore; - SECItem notAfter; - PLArenaPool *arena; -}; - -/* X.509 v3 Authority Key Identifier extension. For the authority certificate - issuer field, we only support URI now. - */ -struct CERTAuthKeyIDStr { - SECItem keyID; /* unique key identifier */ - CERTGeneralName *authCertIssuer; /* CA's issuer name. End with a NULL */ - SECItem authCertSerialNumber; /* CA's certificate serial number */ - SECItem **DERAuthCertIssuer; /* This holds the DER encoded format of - the authCertIssuer field. It is used - by the encoding engine. It should be - used as a read only field by the caller. - */ -}; - -/* x.509 v3 CRL Distributeion Point */ - -/* - * defined the types of CRL Distribution points - */ -typedef enum DistributionPointTypesEnum { - generalName = 1, /* only support this for now */ - relativeDistinguishedName = 2 -} DistributionPointTypes; - -struct CRLDistributionPointStr { - DistributionPointTypes distPointType; - union { - CERTGeneralName *fullName; - CERTRDN relativeName; - } distPoint; - SECItem reasons; - CERTGeneralName *crlIssuer; - - /* Reserved for internal use only*/ - SECItem derDistPoint; - SECItem derRelativeName; - SECItem **derCrlIssuer; - SECItem **derFullName; - SECItem bitsmap; -}; - -struct CERTCrlDistributionPointsStr { - CRLDistributionPoint **distPoints; -}; - -/* - * This structure is used to keep a log of errors when verifying - * a cert chain. This allows multiple errors to be reported all at - * once. - */ -struct CERTVerifyLogNodeStr { - CERTCertificate *cert; /* what cert had the error */ - long error; /* what error was it? */ - unsigned int depth; /* how far up the chain are we */ - void *arg; /* error specific argument */ - struct CERTVerifyLogNodeStr *next; /* next in the list */ - struct CERTVerifyLogNodeStr *prev; /* next in the list */ -}; - - -struct CERTVerifyLogStr { - PLArenaPool *arena; - unsigned int count; - struct CERTVerifyLogNodeStr *head; - struct CERTVerifyLogNodeStr *tail; -}; - - -struct CERTOKDomainNameStr { - CERTOKDomainName *next; - char name[1]; /* actual length may be longer. */ -}; - - -typedef SECStatus (PR_CALLBACK *CERTStatusChecker) (CERTCertDBHandle *handle, - CERTCertificate *cert, - PRTime time, - void *pwArg); - -typedef SECStatus (PR_CALLBACK *CERTStatusDestroy) (CERTStatusConfig *handle); - -struct CERTStatusConfigStr { - CERTStatusChecker statusChecker; /* NULL means no checking enabled */ - CERTStatusDestroy statusDestroy; /* enabled or no, will clean up */ - void *statusContext; /* cx specific to checking protocol */ -}; - -struct CERTAuthInfoAccessStr { - SECItem method; - SECItem derLocation; - CERTGeneralName *location; /* decoded location */ -}; - - -/* This is the typedef for the callback passed to CERT_OpenCertDB() */ -/* callback to return database name based on version number */ -typedef char * (*CERTDBNameFunc)(void *arg, int dbVersion); - -/* - * types of cert packages that we can decode - */ -typedef enum CERTPackageTypeEnum { - certPackageNone = 0, - certPackageCert = 1, - certPackagePKCS7 = 2, - certPackageNSCertSeq = 3, - certPackageNSCertWrap = 4 -} CERTPackageType; - -/* - * these types are for the PKIX Certificate Policies extension - */ -typedef struct { - SECOidTag oid; - SECItem qualifierID; - SECItem qualifierValue; -} CERTPolicyQualifier; - -typedef struct { - SECOidTag oid; - SECItem policyID; - CERTPolicyQualifier **policyQualifiers; -} CERTPolicyInfo; - -typedef struct { - PLArenaPool *arena; - CERTPolicyInfo **policyInfos; -} CERTCertificatePolicies; - -typedef struct { - SECItem organization; - SECItem **noticeNumbers; -} CERTNoticeReference; - -typedef struct { - PLArenaPool *arena; - CERTNoticeReference noticeReference; - SECItem derNoticeReference; - SECItem displayText; -} CERTUserNotice; - -typedef struct { - PLArenaPool *arena; - SECItem **oids; -} CERTOidSequence; - -/* - * these types are for the PKIX Policy Mappings extension - */ -typedef struct { - SECItem issuerDomainPolicy; - SECItem subjectDomainPolicy; -} CERTPolicyMap; - -typedef struct { - PLArenaPool *arena; - CERTPolicyMap **policyMaps; -} CERTCertificatePolicyMappings; - -/* - * these types are for the PKIX inhibitAnyPolicy extension - */ -typedef struct { - SECItem inhibitAnySkipCerts; -} CERTCertificateInhibitAny; - -/* - * these types are for the PKIX Policy Constraints extension - */ -typedef struct { - SECItem explicitPolicySkipCerts; - SECItem inhibitMappingSkipCerts; -} CERTCertificatePolicyConstraints; - -/* - * These types are for the validate chain callback param. - * - * CERTChainVerifyCallback is an application-supplied callback that can be used - * to augment libpkix's certificate chain validation with additional - * application-specific checks. It may be called multiple times if there are - * multiple potentially-valid paths for the certificate being validated. This - * callback is called before revocation checking is done on the certificates in - * the given chain. - * - * - isValidChainArg contains the application-provided opaque argument - * - currentChain is the currently validated chain. It is ordered with the leaf - * certificate at the head and the trust anchor at the tail. - * - * The callback should set *chainOK = PR_TRUE and return SECSuccess if the - * certificate chain is acceptable. It should set *chainOK = PR_FALSE and - * return SECSuccess if the chain is unacceptable, to indicate that the given - * chain is bad and path building should continue. It should return SECFailure - * to indicate an fatal error that will cause path validation to fail - * immediately. - */ -typedef SECStatus (*CERTChainVerifyCallbackFunc) - (void *isChainValidArg, - const CERTCertList *currentChain, - PRBool *chainOK); - -/* - * Note: If extending this structure, it will be necessary to change the - * associated CERTValParamInType - */ -typedef struct { - CERTChainVerifyCallbackFunc isChainValid; - void *isChainValidArg; -} CERTChainVerifyCallback; - -/* - * these types are for the CERT_PKIX* Verification functions - * These are all optional parameters. - */ - -typedef enum { - cert_pi_end = 0, /* SPECIAL: signifies end of array of - * CERTValParam* */ - cert_pi_nbioContext = 1, /* specify a non-blocking IO context used to - * resume a session. If this argument is - * specified, no other arguments should be. - * Specified in value.pointer.p. If the - * operation completes the context will be - * freed. */ - cert_pi_nbioAbort = 2, /* specify a non-blocking IO context for an - * existing operation which the caller wants - * to abort. If this argument is - * specified, no other arguments should be. - * Specified in value.pointer.p. If the - * operation succeeds the context will be - * freed. */ - cert_pi_certList = 3, /* specify the chain to validate against. If - * this value is given, then the path - * construction step in the validation is - * skipped. Specified in value.pointer.chain */ - cert_pi_policyOID = 4, /* validate certificate for policy OID. - * Specified in value.array.oids. Cert must - * be good for at least one OID in order - * to validate. Default is that the user is not - * concerned about certificate policy. */ - cert_pi_policyFlags = 5, /* flags for each policy specified in policyOID. - * Specified in value.scalar.ul. Policy flags - * apply to all specified oids. - * Use CERT_POLICY_FLAG_* macros below. If not - * specified policy flags default to 0 */ - cert_pi_keyusage = 6, /* specify what the keyusages the certificate - * will be evaluated against, specified in - * value.scalar.ui. The cert must validate for - * at least one of the specified key usages. - * Values match the KU_ bit flags defined - * in this file. Default is derived from - * the 'usages' function argument */ - cert_pi_extendedKeyusage= 7, /* specify what the required extended key - * usage of the certificate. Specified as - * an array of oidTags in value.array.oids. - * The cert must validate for at least one - * of the specified extended key usages. - * If not specified, no extended key usages - * will be checked. */ - cert_pi_date = 8, /* validate certificate is valid as of date - * specified in value.scalar.time. A special - * value '0' indicates 'now'. default is '0' */ - cert_pi_revocationFlags = 9, /* Specify what revocation checking to do. - * See CERT_REV_FLAG_* macros below - * Set in value.pointer.revocation */ - cert_pi_certStores = 10,/* Bitmask of Cert Store flags (see below) - * Set in value.scalar.ui */ - cert_pi_trustAnchors = 11,/* Specify the list of trusted roots to - * validate against. - * The default set of trusted roots, these are - * root CA certs from libnssckbi.so or CA - * certs trusted by user, are used in any of - * the following cases: - * * when the parameter is not set. - * * when the list of trust anchors is empty. - * Note that this handling can be further altered by altering the - * cert_pi_useOnlyTrustAnchors flag - * Specified in value.pointer.chain */ - cert_pi_useAIACertFetch = 12, /* Enables cert fetching using AIA extension. - * In NSS 3.12.1 or later. Default is off. - * Value is in value.scalar.b */ - cert_pi_chainVerifyCallback = 13, - /* The callback container for doing extra - * validation on the currently calculated chain. - * Value is in value.pointer.chainVerifyCallback */ - cert_pi_useOnlyTrustAnchors = 14,/* If true, disables trusting any - * certificates other than the ones passed in via cert_pi_trustAnchors. - * If false, then the certificates specified via cert_pi_trustAnchors - * will be combined with the pre-existing trusted roots, but only for - * the certificate validation being performed. - * If no value has been supplied via cert_pi_trustAnchors, this has no - * effect. - * The default value is true, meaning if this is not supplied, only - * trust anchors supplied via cert_pi_trustAnchors are trusted. - * Specified in value.scalar.b */ - cert_pi_max /* SPECIAL: signifies maximum allowed value, - * can increase in future releases */ -} CERTValParamInType; - -/* - * for all out parameters: - * out parameters are only returned if the caller asks for them in - * the CERTValOutParam array. Caller is responsible for the CERTValOutParam - * array itself. The pkix verify function will allocate and other arrays - * pointers, or objects. The Caller is responsible for freeing those results. - * If SECWouldBlock is returned, only cert_pi_nbioContext is returned. - */ -typedef enum { - cert_po_end = 0, /* SPECIAL: signifies end of array of - * CERTValParam* */ - cert_po_nbioContext = 1, /* Return a nonblocking context. If no - * non-blocking context is specified, then - * blocking IO will be used. - * Returned in value.pointer.p. The context is - * freed after an abort or a complete operation. - * This value is only returned on SECWouldBlock. - */ - cert_po_trustAnchor = 2, /* Return the trust anchor for the chain that - * was validated. Returned in - * value.pointer.cert, this value is only - * returned on SECSuccess. */ - cert_po_certList = 3, /* Return the entire chain that was validated. - * Returned in value.pointer.certList. If no - * chain could be constructed, this value - * would be NULL. */ - cert_po_policyOID = 4, /* Return the policies that were found to be - * valid. Returned in value.array.oids as an - * array. This is only returned on - * SECSuccess. */ - cert_po_errorLog = 5, /* Return a log of problems with the chain. - * Returned in value.pointer.log */ - cert_po_usages = 6, /* Return what usages the certificate is valid - for. Returned in value.scalar.usages */ - cert_po_keyUsage = 7, /* Return what key usages the certificate - * is valid for. - * Returned in value.scalar.usage */ - cert_po_extendedKeyusage= 8, /* Return what extended key usages the - * certificate is valid for. - * Returned in value.array.oids */ - cert_po_max /* SPECIAL: signifies maximum allowed value, - * can increase in future releases */ - -} CERTValParamOutType; - -typedef enum { - cert_revocation_method_crl = 0, - cert_revocation_method_ocsp, - cert_revocation_method_count -} CERTRevocationMethodIndex; - - -/* - * The following flags are supposed to be used to control bits in - * each integer contained in the array pointed to be: - * CERTRevocationTests.cert_rev_flags_per_method - * All Flags are prefixed by CERT_REV_M_, where _M_ indicates - * this is a method dependent flag. - */ - -/* - * Whether or not to use a method for revocation testing. - * If set to "do not test", then all other flags are ignored. - */ -#define CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD 0L -#define CERT_REV_M_TEST_USING_THIS_METHOD 1L - -/* - * Whether or not NSS is allowed to attempt to fetch fresh information - * from the network. - * (Although fetching will never happen if fresh information for the - * method is already locally available.) - */ -#define CERT_REV_M_ALLOW_NETWORK_FETCHING 0L -#define CERT_REV_M_FORBID_NETWORK_FETCHING 2L - -/* - * Example for an implicit default source: - * The globally configured default OCSP responder. - * IGNORE means: - * ignore the implicit default source, whether it's configured or not. - * ALLOW means: - * if an implicit default source is configured, - * then it overrides any available or missing source in the cert. - * if no implicit default source is configured, - * then we continue to use what's available (or not available) - * in the certs. - */ -#define CERT_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE 0L -#define CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE 4L - -/* - * Defines the behavior if no fresh information is available, - * fetching from the network is allowed, but the source of revocation - * information is unknown (even after considering implicit sources, - * if allowed by other flags). - * SKIPT_TEST means: - * We ignore that no fresh information is available and - * skip this test. - * REQUIRE_INFO means: - * We still require that fresh information is available. - * Other flags define what happens on missing fresh info. - */ -#define CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE 0L -#define CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE 8L - -/* - * Defines the behavior if we are unable to obtain fresh information. - * INGORE means: - * Return "cert status unknown" - * FAIL means: - * Return "cert revoked". - */ -#define CERT_REV_M_IGNORE_MISSING_FRESH_INFO 0L -#define CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO 16L - -/* - * What should happen if we were able to find fresh information using - * this method, and the data indicated the cert is good? - * STOP_TESTING means: - * Our success is sufficient, do not continue testing - * other methods. - * CONTINUE_TESTING means: - * We will continue and test the next allowed - * specified method. - */ -#define CERT_REV_M_STOP_TESTING_ON_FRESH_INFO 0L -#define CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO 32L - -/* - * The following flags are supposed to be used to control bits in - * CERTRevocationTests.cert_rev_method_independent_flags - * All Flags are prefixed by CERT_REV_M_, where _M_ indicates - * this is a method independent flag. - */ - -/* - * This defines the order to checking. - * EACH_METHOD_SEPARATELY means: - * Do all tests related to a particular allowed method - * (both local information and network fetching) in a single step. - * Only after testing for a particular method is done, - * then switching to the next method will happen. - * ALL_LOCAL_INFORMATION_FIRST means: - * Start by testing the information for all allowed methods - * which are already locally available. Only after that is done - * consider to fetch from the network (as allowed by other flags). - */ -#define CERT_REV_MI_TEST_EACH_METHOD_SEPARATELY 0L -#define CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST 1L - -/* - * Use this flag to specify that it's necessary that fresh information - * is available for at least one of the allowed methods, but it's - * irrelevant which of the mechanisms succeeded. - * NO_OVERALL_INFO_REQUIREMENT means: - * We strictly follow the requirements for each individual method. - * REQUIRE_SOME_FRESH_INFO_AVAILABLE means: - * After the individual tests have been executed, we must have - * been able to find fresh information using at least one method. - * If we were unable to find fresh info, it's a failure. - * This setting overrides the CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO - * flag on all methods. - */ -#define CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT 0L -#define CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE 2L - - -typedef struct { - /* - * The size of the array that cert_rev_flags_per_method points to, - * meaning, the number of methods that are known and defined - * by the caller. - */ - PRUint32 number_of_defined_methods; - - /* - * A pointer to an array of integers. - * Each integer defines revocation checking for a single method, - * by having individual CERT_REV_M_* bits set or not set. - * The meaning of index numbers into this array are defined by - * enum CERTRevocationMethodIndex - * The size of the array must be specified by the caller in the separate - * variable number_of_defined_methods. - * The size of the array may be smaller than - * cert_revocation_method_count, it can happen if a caller - * is not yet aware of the latest revocation methods - * (or does not want to use them). - */ - PRUint64 *cert_rev_flags_per_method; - - /* - * How many preferred methods are specified? - * This is equivalent to the size of the array that - * preferred_revocation_methods points to. - * It's allowed to set this value to zero, - * then NSS will decide which methods to prefer. - */ - PRUint32 number_of_preferred_methods; - - /* Array that may specify an optional order of preferred methods. - * Each array entry shall contain a method identifier as defined - * by CERTRevocationMethodIndex. - * The entry at index [0] specifies the method with highest preferrence. - * These methods will be tested first for locally available information. - * Methods allowed for downloading will be attempted in the same order. - */ - CERTRevocationMethodIndex *preferred_methods; - - /* - * An integer which defines certain aspects of revocation checking - * (independent of individual methods) by having individual - * CERT_REV_MI_* bits set or not set. - */ - PRUint64 cert_rev_method_independent_flags; -} CERTRevocationTests; - -typedef struct { - CERTRevocationTests leafTests; - CERTRevocationTests chainTests; -} CERTRevocationFlags; - -typedef struct CERTValParamInValueStr { - union { - PRBool b; - PRInt32 i; - PRUint32 ui; - PRInt64 l; - PRUint64 ul; - PRTime time; - } scalar; - union { - const void* p; - const char* s; - const CERTCertificate* cert; - const CERTCertList *chain; - const CERTRevocationFlags *revocation; - const CERTChainVerifyCallback *chainVerifyCallback; - } pointer; - union { - const PRInt32 *pi; - const PRUint32 *pui; - const PRInt64 *pl; - const PRUint64 *pul; - const SECOidTag *oids; - } array; - int arraySize; -} CERTValParamInValue; - - -typedef struct CERTValParamOutValueStr { - union { - PRBool b; - PRInt32 i; - PRUint32 ui; - PRInt64 l; - PRUint64 ul; - SECCertificateUsage usages; - } scalar; - union { - void* p; - char* s; - CERTVerifyLog *log; - CERTCertificate* cert; - CERTCertList *chain; - } pointer; - union { - void *p; - SECOidTag *oids; - } array; - int arraySize; -} CERTValParamOutValue; - -typedef struct { - CERTValParamInType type; - CERTValParamInValue value; -} CERTValInParam; - -typedef struct { - CERTValParamOutType type; - CERTValParamOutValue value; -} CERTValOutParam; - -/* - * Levels of standards conformance strictness for CERT_NameToAsciiInvertible - */ -typedef enum CertStrictnessLevels { - CERT_N2A_READABLE = 0, /* maximum human readability */ - CERT_N2A_STRICT = 10, /* strict RFC compliance */ - CERT_N2A_INVERTIBLE = 20 /* maximum invertibility, - all DirectoryStrings encoded in hex */ -} CertStrictnessLevel; - -/* - * policy flag defines - */ -#define CERT_POLICY_FLAG_NO_MAPPING 1 -#define CERT_POLICY_FLAG_EXPLICIT 2 -#define CERT_POLICY_FLAG_NO_ANY 4 - -/* - * CertStore flags - */ -#define CERT_ENABLE_LDAP_FETCH 1 -#define CERT_ENABLE_HTTP_FETCH 2 - -/* This functin pointer type may be used for any function that takes - * a CERTCertificate * and returns an allocated string, which must be - * freed by a call to PORT_Free. - */ -typedef char * (*CERT_StringFromCertFcn)(CERTCertificate *cert); - -/* XXX Lisa thinks the template declarations belong in cert.h, not here? */ - -#include "secasn1t.h" /* way down here because I expect template stuff to - * move out of here anyway */ - -SEC_BEGIN_PROTOS - -extern const SEC_ASN1Template CERT_CertificateRequestTemplate[]; -extern const SEC_ASN1Template CERT_CertificateTemplate[]; -extern const SEC_ASN1Template SEC_SignedCertificateTemplate[]; -extern const SEC_ASN1Template CERT_CertExtensionTemplate[]; -extern const SEC_ASN1Template CERT_SequenceOfCertExtensionTemplate[]; -extern const SEC_ASN1Template SECKEY_PublicKeyTemplate[]; -extern const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[]; -extern const SEC_ASN1Template CERT_TimeChoiceTemplate[]; -extern const SEC_ASN1Template CERT_ValidityTemplate[]; -extern const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[]; -extern const SEC_ASN1Template SEC_CertSequenceTemplate[]; - -extern const SEC_ASN1Template CERT_IssuerAndSNTemplate[]; -extern const SEC_ASN1Template CERT_NameTemplate[]; -extern const SEC_ASN1Template CERT_SetOfSignedCrlTemplate[]; -extern const SEC_ASN1Template CERT_RDNTemplate[]; -extern const SEC_ASN1Template CERT_SignedDataTemplate[]; -extern const SEC_ASN1Template CERT_CrlTemplate[]; -extern const SEC_ASN1Template CERT_SignedCrlTemplate[]; - -/* -** XXX should the attribute stuff be centralized for all of ns/security? -*/ -extern const SEC_ASN1Template CERT_AttributeTemplate[]; -extern const SEC_ASN1Template CERT_SetOfAttributeTemplate[]; - -/* These functions simply return the address of the above-declared templates. -** This is necessary for Windows DLLs. Sigh. -*/ -SEC_ASN1_CHOOSER_DECLARE(CERT_CertificateRequestTemplate) -SEC_ASN1_CHOOSER_DECLARE(CERT_CertificateTemplate) -SEC_ASN1_CHOOSER_DECLARE(CERT_CrlTemplate) -SEC_ASN1_CHOOSER_DECLARE(CERT_IssuerAndSNTemplate) -SEC_ASN1_CHOOSER_DECLARE(CERT_NameTemplate) -SEC_ASN1_CHOOSER_DECLARE(CERT_SequenceOfCertExtensionTemplate) -SEC_ASN1_CHOOSER_DECLARE(CERT_SetOfSignedCrlTemplate) -SEC_ASN1_CHOOSER_DECLARE(CERT_SignedDataTemplate) -SEC_ASN1_CHOOSER_DECLARE(CERT_SubjectPublicKeyInfoTemplate) -SEC_ASN1_CHOOSER_DECLARE(SEC_SignedCertificateTemplate) -SEC_ASN1_CHOOSER_DECLARE(CERT_SignedCrlTemplate) -SEC_ASN1_CHOOSER_DECLARE(CERT_TimeChoiceTemplate) - -SEC_END_PROTOS - -#endif /* _CERTT_H_ */ diff --git a/security/nss/lib/certdb/certv3.c b/security/nss/lib/certdb/certv3.c deleted file mode 100644 index 0af53588f..000000000 --- a/security/nss/lib/certdb/certv3.c +++ /dev/null @@ -1,367 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * Code for dealing with X509.V3 extensions. - * - * $Id$ - */ - -#include "cert.h" -#include "secitem.h" -#include "secoid.h" -#include "secder.h" -#include "secasn1.h" -#include "certxutl.h" -#include "secerr.h" - -SECStatus -CERT_FindCertExtensionByOID(CERTCertificate *cert, SECItem *oid, - SECItem *value) -{ - return (cert_FindExtensionByOID (cert->extensions, oid, value)); -} - - -SECStatus -CERT_FindCertExtension(CERTCertificate *cert, int tag, SECItem *value) -{ - return (cert_FindExtension (cert->extensions, tag, value)); -} - -static void -SetExts(void *object, CERTCertExtension **exts) -{ - CERTCertificate *cert = (CERTCertificate *)object; - - cert->extensions = exts; - DER_SetUInteger (cert->arena, &(cert->version), SEC_CERTIFICATE_VERSION_3); -} - -void * -CERT_StartCertExtensions(CERTCertificate *cert) -{ - return (cert_StartExtensions ((void *)cert, cert->arena, SetExts)); -} - -/* find the given extension in the certificate of the Issuer of 'cert' */ -SECStatus -CERT_FindIssuerCertExtension(CERTCertificate *cert, int tag, SECItem *value) -{ - CERTCertificate *issuercert; - SECStatus rv; - - issuercert = CERT_FindCertByName(cert->dbhandle, &cert->derIssuer); - if ( issuercert ) { - rv = cert_FindExtension(issuercert->extensions, tag, value); - CERT_DestroyCertificate(issuercert); - } else { - rv = SECFailure; - } - - return(rv); -} - -/* find a URL extension in the cert or its CA - * apply the base URL string if it exists - */ -char * -CERT_FindCertURLExtension(CERTCertificate *cert, int tag, int catag) -{ - SECStatus rv; - SECItem urlitem = {siBuffer,0}; - SECItem baseitem = {siBuffer,0}; - SECItem urlstringitem = {siBuffer,0}; - SECItem basestringitem = {siBuffer,0}; - PRArenaPool *arena = NULL; - PRBool hasbase; - char *urlstring; - char *str; - int len; - unsigned int i; - - urlstring = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( ! arena ) { - goto loser; - } - - hasbase = PR_FALSE; - - rv = cert_FindExtension(cert->extensions, tag, &urlitem); - if ( rv == SECSuccess ) { - rv = cert_FindExtension(cert->extensions, SEC_OID_NS_CERT_EXT_BASE_URL, - &baseitem); - if ( rv == SECSuccess ) { - hasbase = PR_TRUE; - } - - } else if ( catag ) { - /* if the cert doesn't have the extensions, see if the issuer does */ - rv = CERT_FindIssuerCertExtension(cert, catag, &urlitem); - if ( rv != SECSuccess ) { - goto loser; - } - rv = CERT_FindIssuerCertExtension(cert, SEC_OID_NS_CERT_EXT_BASE_URL, - &baseitem); - if ( rv == SECSuccess ) { - hasbase = PR_TRUE; - } - } else { - goto loser; - } - - rv = SEC_QuickDERDecodeItem(arena, &urlstringitem, - SEC_ASN1_GET(SEC_IA5StringTemplate), &urlitem); - - if ( rv != SECSuccess ) { - goto loser; - } - if ( hasbase ) { - rv = SEC_QuickDERDecodeItem(arena, &basestringitem, - SEC_ASN1_GET(SEC_IA5StringTemplate), - &baseitem); - - if ( rv != SECSuccess ) { - goto loser; - } - } - - len = urlstringitem.len + ( hasbase ? basestringitem.len : 0 ) + 1; - - str = urlstring = (char *)PORT_Alloc(len); - if ( urlstring == NULL ) { - goto loser; - } - - /* copy the URL base first */ - if ( hasbase ) { - - /* if the urlstring has a : in it, then we assume it is an absolute - * URL, and will not get the base string pre-pended - */ - for ( i = 0; i < urlstringitem.len; i++ ) { - if ( urlstringitem.data[i] == ':' ) { - goto nobase; - } - } - - PORT_Memcpy(str, basestringitem.data, basestringitem.len); - str += basestringitem.len; - - } - -nobase: - /* copy the rest (or all) of the URL */ - PORT_Memcpy(str, urlstringitem.data, urlstringitem.len); - str += urlstringitem.len; - - *str = '\0'; - goto done; - -loser: - if ( urlstring ) { - PORT_Free(urlstring); - } - - urlstring = NULL; -done: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - if ( baseitem.data ) { - PORT_Free(baseitem.data); - } - if ( urlitem.data ) { - PORT_Free(urlitem.data); - } - - return(urlstring); -} - -/* - * get the value of the Netscape Certificate Type Extension - */ -SECStatus -CERT_FindNSCertTypeExtension(CERTCertificate *cert, SECItem *retItem) -{ - - return (CERT_FindBitStringExtension - (cert->extensions, SEC_OID_NS_CERT_EXT_CERT_TYPE, retItem)); -} - - -/* - * get the value of a string type extension - */ -char * -CERT_FindNSStringExtension(CERTCertificate *cert, int oidtag) -{ - SECItem wrapperItem, tmpItem = {siBuffer,0}; - SECStatus rv; - PRArenaPool *arena = NULL; - char *retstring = NULL; - - wrapperItem.data = NULL; - tmpItem.data = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - - if ( ! arena ) { - goto loser; - } - - rv = cert_FindExtension(cert->extensions, oidtag, - &wrapperItem); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = SEC_QuickDERDecodeItem(arena, &tmpItem, - SEC_ASN1_GET(SEC_IA5StringTemplate), &wrapperItem); - - if ( rv != SECSuccess ) { - goto loser; - } - - retstring = (char *)PORT_Alloc(tmpItem.len + 1 ); - if ( retstring == NULL ) { - goto loser; - } - - PORT_Memcpy(retstring, tmpItem.data, tmpItem.len); - retstring[tmpItem.len] = '\0'; - -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - if ( wrapperItem.data ) { - PORT_Free(wrapperItem.data); - } - - return(retstring); -} - -/* - * get the value of the X.509 v3 Key Usage Extension - */ -SECStatus -CERT_FindKeyUsageExtension(CERTCertificate *cert, SECItem *retItem) -{ - - return (CERT_FindBitStringExtension(cert->extensions, - SEC_OID_X509_KEY_USAGE, retItem)); -} - -/* - * get the value of the X.509 v3 Key Usage Extension - */ -SECStatus -CERT_FindSubjectKeyIDExtension(CERTCertificate *cert, SECItem *retItem) -{ - - SECStatus rv; - SECItem encodedValue = {siBuffer, NULL, 0 }; - SECItem decodedValue = {siBuffer, NULL, 0 }; - - rv = cert_FindExtension - (cert->extensions, SEC_OID_X509_SUBJECT_KEY_ID, &encodedValue); - if (rv == SECSuccess) { - PLArenaPool * tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (tmpArena) { - rv = SEC_QuickDERDecodeItem(tmpArena, &decodedValue, - SEC_ASN1_GET(SEC_OctetStringTemplate), - &encodedValue); - if (rv == SECSuccess) { - rv = SECITEM_CopyItem(NULL, retItem, &decodedValue); - } - PORT_FreeArena(tmpArena, PR_FALSE); - } else { - rv = SECFailure; - } - } - SECITEM_FreeItem(&encodedValue, PR_FALSE); - return rv; -} - -SECStatus -CERT_FindBasicConstraintExten(CERTCertificate *cert, - CERTBasicConstraints *value) -{ - SECItem encodedExtenValue; - SECStatus rv; - - encodedExtenValue.data = NULL; - encodedExtenValue.len = 0; - - rv = cert_FindExtension(cert->extensions, SEC_OID_X509_BASIC_CONSTRAINTS, - &encodedExtenValue); - if ( rv != SECSuccess ) { - return (rv); - } - - rv = CERT_DecodeBasicConstraintValue (value, &encodedExtenValue); - - /* free the raw extension data */ - PORT_Free(encodedExtenValue.data); - encodedExtenValue.data = NULL; - - return(rv); -} - -CERTAuthKeyID * -CERT_FindAuthKeyIDExten (PRArenaPool *arena, CERTCertificate *cert) -{ - SECItem encodedExtenValue; - SECStatus rv; - CERTAuthKeyID *ret; - - encodedExtenValue.data = NULL; - encodedExtenValue.len = 0; - - rv = cert_FindExtension(cert->extensions, SEC_OID_X509_AUTH_KEY_ID, - &encodedExtenValue); - if ( rv != SECSuccess ) { - return (NULL); - } - - ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue); - - PORT_Free(encodedExtenValue.data); - encodedExtenValue.data = NULL; - - return(ret); -} - -SECStatus -CERT_CheckCertUsage(CERTCertificate *cert, unsigned char usage) -{ - SECItem keyUsage; - SECStatus rv; - - /* There is no extension, v1 or v2 certificate */ - if (cert->extensions == NULL) { - return (SECSuccess); - } - - keyUsage.data = NULL; - - /* This code formerly ignored the Key Usage extension if it was - ** marked non-critical. That was wrong. Since we do understand it, - ** we are obligated to honor it, whether or not it is critical. - */ - rv = CERT_FindKeyUsageExtension(cert, &keyUsage); - if (rv == SECFailure) { - rv = (PORT_GetError () == SEC_ERROR_EXTENSION_NOT_FOUND) ? - SECSuccess : SECFailure; - } else if (!(keyUsage.data[0] & usage)) { - PORT_SetError (SEC_ERROR_CERT_USAGES_INVALID); - rv = SECFailure; - } - PORT_Free (keyUsage.data); - return (rv); -} diff --git a/security/nss/lib/certdb/certxutl.c b/security/nss/lib/certdb/certxutl.c deleted file mode 100644 index def071224..000000000 --- a/security/nss/lib/certdb/certxutl.c +++ /dev/null @@ -1,499 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * Certificate Extensions handling code - * - */ - -#include "cert.h" -#include "secitem.h" -#include "secoid.h" -#include "secder.h" -#include "secasn1.h" -#include "certxutl.h" -#include "secerr.h" - -#ifdef OLD -#include "ocspti.h" /* XXX a better extensions interface would not - * require knowledge of data structures of callers */ -#endif - -static CERTCertExtension * -GetExtension (CERTCertExtension **extensions, SECItem *oid) -{ - CERTCertExtension **exts; - CERTCertExtension *ext = NULL; - SECComparison comp; - - exts = extensions; - - if (exts) { - while ( *exts ) { - ext = *exts; - comp = SECITEM_CompareItem(oid, &ext->id); - if ( comp == SECEqual ) - break; - - exts++; - } - return (*exts ? ext : NULL); - } - return (NULL); -} - -SECStatus -cert_FindExtensionByOID (CERTCertExtension **extensions, SECItem *oid, SECItem *value) -{ - CERTCertExtension *ext; - SECStatus rv = SECSuccess; - - ext = GetExtension (extensions, oid); - if (ext == NULL) { - PORT_SetError (SEC_ERROR_EXTENSION_NOT_FOUND); - return (SECFailure); - } - if (value) - rv = SECITEM_CopyItem(NULL, value, &ext->value); - return (rv); -} - - -SECStatus -CERT_GetExtenCriticality (CERTCertExtension **extensions, int tag, PRBool *isCritical) -{ - CERTCertExtension *ext; - SECOidData *oid; - - if (!isCritical) - return (SECSuccess); - - /* find the extension in the extensions list */ - oid = SECOID_FindOIDByTag((SECOidTag)tag); - if ( !oid ) { - return(SECFailure); - } - ext = GetExtension (extensions, &oid->oid); - if (ext == NULL) { - PORT_SetError (SEC_ERROR_EXTENSION_NOT_FOUND); - return (SECFailure); - } - - /* If the criticality is omitted, then it is false by default. - ex->critical.data is NULL */ - if (ext->critical.data == NULL) - *isCritical = PR_FALSE; - else - *isCritical = (ext->critical.data[0] == 0xff) ? PR_TRUE : PR_FALSE; - return (SECSuccess); -} - -SECStatus -cert_FindExtension(CERTCertExtension **extensions, int tag, SECItem *value) -{ - SECOidData *oid; - - oid = SECOID_FindOIDByTag((SECOidTag)tag); - if ( !oid ) { - return(SECFailure); - } - - return(cert_FindExtensionByOID(extensions, &oid->oid, value)); -} - - -typedef struct _extNode { - struct _extNode *next; - CERTCertExtension *ext; -} extNode; - -typedef struct { - void (*setExts)(void *object, CERTCertExtension **exts); - void *object; - PRArenaPool *ownerArena; - PRArenaPool *arena; - extNode *head; - int count; -}extRec; - -/* - * cert_StartExtensions - * - * NOTE: This interface changed significantly to remove knowledge - * about callers data structures (owner objects) - */ -void * -cert_StartExtensions(void *owner, PRArenaPool *ownerArena, - void (*setExts)(void *object, CERTCertExtension **exts)) -{ - PRArenaPool *arena; - extRec *handle; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( !arena ) { - return(0); - } - - handle = (extRec *)PORT_ArenaAlloc(arena, sizeof(extRec)); - if ( !handle ) { - PORT_FreeArena(arena, PR_FALSE); - return(0); - } - - handle->object = owner; - handle->ownerArena = ownerArena; - handle->setExts = setExts; - - handle->arena = arena; - handle->head = 0; - handle->count = 0; - - return(handle); -} - -static unsigned char hextrue = 0xff; - -/* - * Note - assumes that data pointed to by oid->data will not move - */ -SECStatus -CERT_AddExtensionByOID (void *exthandle, SECItem *oid, SECItem *value, - PRBool critical, PRBool copyData) -{ - CERTCertExtension *ext; - SECStatus rv; - extNode *node; - extRec *handle; - - handle = (extRec *)exthandle; - - /* allocate space for extension and list node */ - ext = (CERTCertExtension*)PORT_ArenaZAlloc(handle->ownerArena, - sizeof(CERTCertExtension)); - if ( !ext ) { - return(SECFailure); - } - - node = (extNode*)PORT_ArenaAlloc(handle->arena, sizeof(extNode)); - if ( !node ) { - return(SECFailure); - } - - /* add to list */ - node->next = handle->head; - handle->head = node; - - /* point to ext struct */ - node->ext = ext; - - /* the object ID of the extension */ - ext->id = *oid; - - /* set critical field */ - if ( critical ) { - ext->critical.data = (unsigned char*)&hextrue; - ext->critical.len = 1; - } - - /* set the value */ - if ( copyData ) { - rv = SECITEM_CopyItem(handle->ownerArena, &ext->value, value); - if ( rv ) { - return(SECFailure); - } - } else { - ext->value = *value; - } - - handle->count++; - - return(SECSuccess); - -} - -SECStatus -CERT_AddExtension(void *exthandle, int idtag, SECItem *value, - PRBool critical, PRBool copyData) -{ - SECOidData *oid; - - oid = SECOID_FindOIDByTag((SECOidTag)idtag); - if ( !oid ) { - return(SECFailure); - } - - return(CERT_AddExtensionByOID(exthandle, &oid->oid, value, critical, copyData)); -} - -SECStatus -CERT_EncodeAndAddExtension(void *exthandle, int idtag, void *value, - PRBool critical, const SEC_ASN1Template *atemplate) -{ - extRec *handle; - SECItem *encitem; - - handle = (extRec *)exthandle; - - encitem = SEC_ASN1EncodeItem(handle->ownerArena, NULL, value, atemplate); - if ( encitem == NULL ) { - return(SECFailure); - } - - return CERT_AddExtension(exthandle, idtag, encitem, critical, PR_FALSE); -} - -void -PrepareBitStringForEncoding (SECItem *bitsmap, SECItem *value) -{ - unsigned char onebyte; - unsigned int i, len = 0; - - /* to prevent warning on some platform at compile time */ - onebyte = '\0'; - /* Get the position of the right-most turn-on bit */ - for (i = 0; i < (value->len ) * 8; ++i) { - if (i % 8 == 0) - onebyte = value->data[i/8]; - if (onebyte & 0x80) - len = i; - onebyte <<= 1; - - } - bitsmap->data = value->data; - /* Add one here since we work with base 1 */ - bitsmap->len = len + 1; -} - -SECStatus -CERT_EncodeAndAddBitStrExtension (void *exthandle, int idtag, - SECItem *value, PRBool critical) -{ - SECItem bitsmap; - - PrepareBitStringForEncoding (&bitsmap, value); - return (CERT_EncodeAndAddExtension - (exthandle, idtag, &bitsmap, critical, - SEC_ASN1_GET(SEC_BitStringTemplate))); -} - -SECStatus -CERT_FinishExtensions(void *exthandle) -{ - extRec *handle; - extNode *node; - CERTCertExtension **exts; - SECStatus rv = SECFailure; - - handle = (extRec *)exthandle; - - /* allocate space for extensions array */ - exts = PORT_ArenaNewArray(handle->ownerArena, CERTCertExtension *, - handle->count + 1); - if (exts == NULL) { - goto loser; - } - - /* put extensions in owner object and update its version number */ - -#ifdef OLD - switch (handle->type) { - case CertificateExtensions: - handle->owner.cert->extensions = exts; - DER_SetUInteger (ownerArena, &(handle->owner.cert->version), - SEC_CERTIFICATE_VERSION_3); - break; - case CrlExtensions: - handle->owner.crl->extensions = exts; - DER_SetUInteger (ownerArena, &(handle->owner.crl->version), - SEC_CRL_VERSION_2); - break; - case OCSPRequestExtensions: - handle->owner.request->tbsRequest->requestExtensions = exts; - break; - case OCSPSingleRequestExtensions: - handle->owner.singleRequest->singleRequestExtensions = exts; - break; - case OCSPResponseSingleExtensions: - handle->owner.singleResponse->singleExtensions = exts; - break; - } -#endif - - handle->setExts(handle->object, exts); - - /* update the version number */ - - /* copy each extension pointer */ - node = handle->head; - while ( node ) { - *exts = node->ext; - - node = node->next; - exts++; - } - - /* terminate the array of extensions */ - *exts = 0; - - rv = SECSuccess; - -loser: - /* free working arena */ - PORT_FreeArena(handle->arena, PR_FALSE); - return rv; -} - -SECStatus -CERT_MergeExtensions(void *exthandle, CERTCertExtension **extensions) -{ - CERTCertExtension *ext; - SECStatus rv = SECSuccess; - SECOidTag tag; - extNode *node; - extRec *handle = exthandle; - - if (!exthandle || !extensions) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - while ((ext = *extensions++) != NULL) { - tag = SECOID_FindOIDTag(&ext->id); - for (node=handle->head; node != NULL; node=node->next) { - if (tag == 0) { - if (SECITEM_ItemsAreEqual(&ext->id, &node->ext->id)) - break; - } - else { - if (SECOID_FindOIDTag(&node->ext->id) == tag) { - break; - } - } - } - if (node == NULL) { - PRBool critical = (ext->critical.len != 0 && - ext->critical.data[ext->critical.len - 1] != 0); - if (critical && tag == SEC_OID_UNKNOWN) { - PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION); - rv = SECFailure; - break; - } - /* add to list */ - rv = CERT_AddExtensionByOID (exthandle, &ext->id, &ext->value, - critical, PR_TRUE); - if (rv != SECSuccess) - break; - } - } - return rv; -} - -/* - * get the value of the Netscape Certificate Type Extension - */ -SECStatus -CERT_FindBitStringExtension (CERTCertExtension **extensions, int tag, - SECItem *retItem) -{ - SECItem wrapperItem, tmpItem = {siBuffer,0}; - SECStatus rv; - PRArenaPool *arena = NULL; - - wrapperItem.data = NULL; - tmpItem.data = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - - if ( ! arena ) { - return(SECFailure); - } - - rv = cert_FindExtension(extensions, tag, &wrapperItem); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = SEC_QuickDERDecodeItem(arena, &tmpItem, - SEC_ASN1_GET(SEC_BitStringTemplate), - &wrapperItem); - - if ( rv != SECSuccess ) { - goto loser; - } - - retItem->data = (unsigned char *)PORT_Alloc( ( tmpItem.len + 7 ) >> 3 ); - if ( retItem->data == NULL ) { - goto loser; - } - - PORT_Memcpy(retItem->data, tmpItem.data, ( tmpItem.len + 7 ) >> 3); - retItem->len = tmpItem.len; - - rv = SECSuccess; - goto done; - -loser: - rv = SECFailure; - -done: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - if ( wrapperItem.data ) { - PORT_Free(wrapperItem.data); - } - - return(rv); -} - -PRBool -cert_HasCriticalExtension (CERTCertExtension **extensions) -{ - CERTCertExtension **exts; - CERTCertExtension *ext = NULL; - PRBool hasCriticalExten = PR_FALSE; - - exts = extensions; - - if (exts) { - while ( *exts ) { - ext = *exts; - /* If the criticality is omitted, it's non-critical */ - if (ext->critical.data && ext->critical.data[0] == 0xff) { - hasCriticalExten = PR_TRUE; - break; - } - exts++; - } - } - return (hasCriticalExten); -} - -PRBool -cert_HasUnknownCriticalExten (CERTCertExtension **extensions) -{ - CERTCertExtension **exts; - CERTCertExtension *ext = NULL; - PRBool hasUnknownCriticalExten = PR_FALSE; - - exts = extensions; - - if (exts) { - while ( *exts ) { - ext = *exts; - /* If the criticality is omitted, it's non-critical. - If an extension is critical, make sure that we know - how to process the extension. - */ - if (ext->critical.data && ext->critical.data[0] == 0xff) { - if (SECOID_KnownCertExtenOID (&ext->id) == PR_FALSE) { - hasUnknownCriticalExten = PR_TRUE; - break; - } - } - exts++; - } - } - return (hasUnknownCriticalExten); -} diff --git a/security/nss/lib/certdb/certxutl.h b/security/nss/lib/certdb/certxutl.h deleted file mode 100644 index 05ad572fd..000000000 --- a/security/nss/lib/certdb/certxutl.h +++ /dev/null @@ -1,50 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * x.509 v3 certificate extension helper routines - * - */ - - -#ifndef _CERTXUTL_H_ -#define _CERTXUTL_H_ - -#include "nspr.h" - -#ifdef OLD -typedef enum { - CertificateExtensions, - CrlExtensions, - OCSPRequestExtensions, - OCSPSingleRequestExtensions, - OCSPResponseSingleExtensions -} ExtensionsType; -#endif - -extern PRBool -cert_HasCriticalExtension (CERTCertExtension **extensions); - -extern SECStatus -CERT_FindBitStringExtension (CERTCertExtension **extensions, - int tag, SECItem *retItem); -extern void * -cert_StartExtensions (void *owner, PLArenaPool *arena, - void (*setExts)(void *object, CERTCertExtension **exts)); - -extern SECStatus -cert_FindExtension (CERTCertExtension **extensions, int tag, SECItem *value); - -extern SECStatus -cert_FindExtensionByOID (CERTCertExtension **extensions, - SECItem *oid, SECItem *value); - -extern SECStatus -cert_GetExtenCriticality (CERTCertExtension **extensions, - int tag, PRBool *isCritical); - -extern PRBool -cert_HasUnknownCriticalExten (CERTCertExtension **extensions); - -#endif diff --git a/security/nss/lib/certdb/config.mk b/security/nss/lib/certdb/config.mk deleted file mode 100644 index b8c03de79..000000000 --- a/security/nss/lib/certdb/config.mk +++ /dev/null @@ -1,15 +0,0 @@ -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -# -# Override TARGETS variable so that only static libraries -# are specifed as dependencies within rules.mk. -# - -TARGETS = $(LIBRARY) -SHARED_LIBRARY = -IMPORT_LIBRARY = -PROGRAM = - diff --git a/security/nss/lib/certdb/crl.c b/security/nss/lib/certdb/crl.c deleted file mode 100644 index 8bb446cf3..000000000 --- a/security/nss/lib/certdb/crl.c +++ /dev/null @@ -1,3373 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * Moved from secpkcs7.c - * - * $Id$ - */ - -#include "cert.h" -#include "certi.h" -#include "secder.h" -#include "secasn1.h" -#include "secoid.h" -#include "certdb.h" -#include "certxutl.h" -#include "prtime.h" -#include "secerr.h" -#include "pk11func.h" -#include "dev.h" -#include "dev3hack.h" -#include "nssbase.h" -#if defined(DPC_RWLOCK) || defined(GLOBAL_RWLOCK) -#include "nssrwlk.h" -#endif -#include "pk11priv.h" - -const SEC_ASN1Template SEC_CERTExtensionTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTCertExtension) }, - { SEC_ASN1_OBJECT_ID, - offsetof(CERTCertExtension,id) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */ - offsetof(CERTCertExtension,critical), }, - { SEC_ASN1_OCTET_STRING, - offsetof(CERTCertExtension,value) }, - { 0, } -}; - -static const SEC_ASN1Template SEC_CERTExtensionsTemplate[] = { - { SEC_ASN1_SEQUENCE_OF, 0, SEC_CERTExtensionTemplate} -}; - -/* - * XXX Also, these templates need to be tested; Lisa did the obvious - * translation but they still should be verified. - */ - -const SEC_ASN1Template CERT_IssuerAndSNTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTIssuerAndSN) }, - { SEC_ASN1_SAVE, - offsetof(CERTIssuerAndSN,derIssuer) }, - { SEC_ASN1_INLINE, - offsetof(CERTIssuerAndSN,issuer), - CERT_NameTemplate }, - { SEC_ASN1_INTEGER, - offsetof(CERTIssuerAndSN,serialNumber) }, - { 0 } -}; - -SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) -SEC_ASN1_MKSUB(CERT_TimeChoiceTemplate) - -static const SEC_ASN1Template cert_CrlKeyTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTCrlKey) }, - { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(CERTCrlKey,dummy) }, - { SEC_ASN1_SKIP }, - { SEC_ASN1_ANY, offsetof(CERTCrlKey,derName) }, - { SEC_ASN1_SKIP_REST }, - { 0 } -}; - -static const SEC_ASN1Template cert_CrlEntryTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTCrlEntry) }, - { SEC_ASN1_INTEGER, - offsetof(CERTCrlEntry,serialNumber) }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(CERTCrlEntry,revocationDate), - SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF, - offsetof(CERTCrlEntry, extensions), - SEC_CERTExtensionTemplate}, - { 0 } -}; - -const SEC_ASN1Template CERT_CrlTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTCrl) }, - { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof (CERTCrl, version) }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(CERTCrl,signatureAlg), - SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)}, - { SEC_ASN1_SAVE, - offsetof(CERTCrl,derName) }, - { SEC_ASN1_INLINE, - offsetof(CERTCrl,name), - CERT_NameTemplate }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(CERTCrl,lastUpdate), - SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, - { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_XTRN, - offsetof(CERTCrl,nextUpdate), - SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF, - offsetof(CERTCrl,entries), - cert_CrlEntryTemplate }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | - SEC_ASN1_EXPLICIT | 0, - offsetof(CERTCrl,extensions), - SEC_CERTExtensionsTemplate}, - { 0 } -}; - -const SEC_ASN1Template CERT_CrlTemplateNoEntries[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTCrl) }, - { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof (CERTCrl, version) }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(CERTCrl,signatureAlg), - SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, - { SEC_ASN1_SAVE, - offsetof(CERTCrl,derName) }, - { SEC_ASN1_INLINE, - offsetof(CERTCrl,name), - CERT_NameTemplate }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(CERTCrl,lastUpdate), - SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, - { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_XTRN, - offsetof(CERTCrl,nextUpdate), - SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF | - SEC_ASN1_SKIP }, /* skip entries */ - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | - SEC_ASN1_EXPLICIT | 0, - offsetof(CERTCrl,extensions), - SEC_CERTExtensionsTemplate }, - { 0 } -}; - -const SEC_ASN1Template CERT_CrlTemplateEntriesOnly[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTCrl) }, - { SEC_ASN1_SKIP | SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL }, - { SEC_ASN1_SKIP }, - { SEC_ASN1_SKIP }, - { SEC_ASN1_SKIP | SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(CERTCrl,lastUpdate), - SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, - { SEC_ASN1_SKIP | SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_XTRN, - offsetof(CERTCrl,nextUpdate), - SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF, - offsetof(CERTCrl,entries), - cert_CrlEntryTemplate }, /* decode entries */ - { SEC_ASN1_SKIP_REST }, - { 0 } -}; - -const SEC_ASN1Template CERT_SignedCrlTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTSignedCrl) }, - { SEC_ASN1_SAVE, - offsetof(CERTSignedCrl,signatureWrap.data) }, - { SEC_ASN1_INLINE, - offsetof(CERTSignedCrl,crl), - CERT_CrlTemplate }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN , - offsetof(CERTSignedCrl,signatureWrap.signatureAlgorithm), - SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, - { SEC_ASN1_BIT_STRING, - offsetof(CERTSignedCrl,signatureWrap.signature) }, - { 0 } -}; - -static const SEC_ASN1Template cert_SignedCrlTemplateNoEntries[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTSignedCrl) }, - { SEC_ASN1_SAVE, - offsetof(CERTSignedCrl,signatureWrap.data) }, - { SEC_ASN1_INLINE, - offsetof(CERTSignedCrl,crl), - CERT_CrlTemplateNoEntries }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(CERTSignedCrl,signatureWrap.signatureAlgorithm), - SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, - { SEC_ASN1_BIT_STRING, - offsetof(CERTSignedCrl,signatureWrap.signature) }, - { 0 } -}; - -const SEC_ASN1Template CERT_SetOfSignedCrlTemplate[] = { - { SEC_ASN1_SET_OF, 0, CERT_SignedCrlTemplate }, -}; - -/* get CRL version */ -int cert_get_crl_version(CERTCrl * crl) -{ - /* CRL version is defaulted to v1 */ - int version = SEC_CRL_VERSION_1; - if (crl && crl->version.data != 0) { - version = (int)DER_GetUInteger (&crl->version); - } - return version; -} - - -/* check the entries in the CRL */ -SECStatus cert_check_crl_entries (CERTCrl *crl) -{ - CERTCrlEntry **entries; - CERTCrlEntry *entry; - PRBool hasCriticalExten = PR_FALSE; - SECStatus rv = SECSuccess; - - if (!crl) { - return SECFailure; - } - - if (crl->entries == NULL) { - /* CRLs with no entries are valid */ - return (SECSuccess); - } - - /* Look in the crl entry extensions. If there is a critical extension, - then the crl version must be v2; otherwise, it should be v1. - */ - entries = crl->entries; - while (*entries) { - entry = *entries; - if (entry->extensions) { - /* If there is a critical extension in the entries, then the - CRL must be of version 2. If we already saw a critical extension, - there is no need to check the version again. - */ - if (hasCriticalExten == PR_FALSE) { - hasCriticalExten = cert_HasCriticalExtension (entry->extensions); - if (hasCriticalExten) { - if (cert_get_crl_version(crl) != SEC_CRL_VERSION_2) { - /* only CRL v2 critical extensions are supported */ - PORT_SetError(SEC_ERROR_CRL_V1_CRITICAL_EXTENSION); - rv = SECFailure; - break; - } - } - } - - /* For each entry, make sure that it does not contain an unknown - critical extension. If it does, we must reject the CRL since - we don't know how to process the extension. - */ - if (cert_HasUnknownCriticalExten (entry->extensions) == PR_TRUE) { - PORT_SetError (SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION); - rv = SECFailure; - break; - } - } - ++entries; - } - return(rv); -} - -/* Check the version of the CRL. If there is a critical extension in the crl - or crl entry, then the version must be v2. Otherwise, it should be v1. If - the crl contains critical extension(s), then we must recognized the - extension's OID. - */ -SECStatus cert_check_crl_version (CERTCrl *crl) -{ - PRBool hasCriticalExten = PR_FALSE; - int version = cert_get_crl_version(crl); - - if (version > SEC_CRL_VERSION_2) { - PORT_SetError (SEC_ERROR_CRL_INVALID_VERSION); - return (SECFailure); - } - - /* Check the crl extensions for a critial extension. If one is found, - and the version is not v2, then we are done. - */ - if (crl->extensions) { - hasCriticalExten = cert_HasCriticalExtension (crl->extensions); - if (hasCriticalExten) { - if (version != SEC_CRL_VERSION_2) { - /* only CRL v2 critical extensions are supported */ - PORT_SetError(SEC_ERROR_CRL_V1_CRITICAL_EXTENSION); - return (SECFailure); - } - /* make sure that there is no unknown critical extension */ - if (cert_HasUnknownCriticalExten (crl->extensions) == PR_TRUE) { - PORT_SetError (SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION); - return (SECFailure); - } - } - } - - return (SECSuccess); -} - -/* - * Generate a database key, based on the issuer name from a - * DER crl. - */ -SECStatus -CERT_KeyFromDERCrl(PRArenaPool *arena, SECItem *derCrl, SECItem *key) -{ - SECStatus rv; - CERTSignedData sd; - CERTCrlKey crlkey; - PRArenaPool* myArena; - - if (!arena) { - /* arena needed for QuickDER */ - myArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - } else { - myArena = arena; - } - PORT_Memset (&sd, 0, sizeof (sd)); - rv = SEC_QuickDERDecodeItem (myArena, &sd, CERT_SignedDataTemplate, derCrl); - if (SECSuccess == rv) { - PORT_Memset (&crlkey, 0, sizeof (crlkey)); - rv = SEC_QuickDERDecodeItem(myArena, &crlkey, cert_CrlKeyTemplate, &sd.data); - } - - /* make a copy so the data doesn't point to memory inside derCrl, which - may be temporary */ - if (SECSuccess == rv) { - rv = SECITEM_CopyItem(arena, key, &crlkey.derName); - } - - if (myArena != arena) { - PORT_FreeArena(myArena, PR_FALSE); - } - - return rv; -} - -#define GetOpaqueCRLFields(x) ((OpaqueCRLFields*)x->opaque) - -SECStatus CERT_CompleteCRLDecodeEntries(CERTSignedCrl* crl) -{ - SECStatus rv = SECSuccess; - SECItem* crldata = NULL; - OpaqueCRLFields* extended = NULL; - - if ( (!crl) || - (!(extended = (OpaqueCRLFields*) crl->opaque)) || - (PR_TRUE == extended->decodingError) ) { - rv = SECFailure; - } else { - if (PR_FALSE == extended->partial) { - /* the CRL has already been fully decoded */ - return SECSuccess; - } - if (PR_TRUE == extended->badEntries) { - /* the entries decoding already failed */ - return SECFailure; - } - crldata = &crl->signatureWrap.data; - if (!crldata) { - rv = SECFailure; - } - } - - if (SECSuccess == rv) { - rv = SEC_QuickDERDecodeItem(crl->arena, - &crl->crl, - CERT_CrlTemplateEntriesOnly, - crldata); - if (SECSuccess == rv) { - extended->partial = PR_FALSE; /* successful decode, avoid - decoding again */ - } else { - extended->decodingError = PR_TRUE; - extended->badEntries = PR_TRUE; - /* cache the decoding failure. If it fails the first time, - it will fail again, which will grow the arena and leak - memory, so we want to avoid it */ - } - rv = cert_check_crl_entries(&crl->crl); - if (rv != SECSuccess) { - extended->badExtensions = PR_TRUE; - } - } - return rv; -} - -/* - * take a DER CRL and decode it into a CRL structure - * allow reusing the input DER without making a copy - */ -CERTSignedCrl * -CERT_DecodeDERCrlWithFlags(PRArenaPool *narena, SECItem *derSignedCrl, - int type, PRInt32 options) -{ - PRArenaPool *arena; - CERTSignedCrl *crl; - SECStatus rv; - OpaqueCRLFields* extended = NULL; - const SEC_ASN1Template* crlTemplate = CERT_SignedCrlTemplate; - PRInt32 testOptions = options; - - PORT_Assert(derSignedCrl); - if (!derSignedCrl) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - - /* Adopting DER requires not copying it. Code that sets ADOPT flag - * but doesn't set DONT_COPY probably doesn't know What it is doing. - * That condition is a programming error in the caller. - */ - testOptions &= (CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_DONT_COPY_DER); - PORT_Assert(testOptions != CRL_DECODE_ADOPT_HEAP_DER); - if (testOptions == CRL_DECODE_ADOPT_HEAP_DER) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - - /* make a new arena if needed */ - if (narena == NULL) { - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( !arena ) { - return NULL; - } - } else { - arena = narena; - } - - /* allocate the CRL structure */ - crl = (CERTSignedCrl *)PORT_ArenaZAlloc(arena, sizeof(CERTSignedCrl)); - if ( !crl ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - crl->arena = arena; - - /* allocate opaque fields */ - crl->opaque = (void*)PORT_ArenaZAlloc(arena, sizeof(OpaqueCRLFields)); - if ( !crl->opaque ) { - goto loser; - } - extended = (OpaqueCRLFields*) crl->opaque; - if (options & CRL_DECODE_ADOPT_HEAP_DER) { - extended->heapDER = PR_TRUE; - } - if (options & CRL_DECODE_DONT_COPY_DER) { - crl->derCrl = derSignedCrl; /* DER is not copied . The application - must keep derSignedCrl until it - destroys the CRL */ - } else { - crl->derCrl = (SECItem *)PORT_ArenaZAlloc(arena,sizeof(SECItem)); - if (crl->derCrl == NULL) { - goto loser; - } - rv = SECITEM_CopyItem(arena, crl->derCrl, derSignedCrl); - if (rv != SECSuccess) { - goto loser; - } - } - - /* Save the arena in the inner crl for CRL extensions support */ - crl->crl.arena = arena; - if (options & CRL_DECODE_SKIP_ENTRIES) { - crlTemplate = cert_SignedCrlTemplateNoEntries; - extended->partial = PR_TRUE; - } - - /* decode the CRL info */ - switch (type) { - case SEC_CRL_TYPE: - rv = SEC_QuickDERDecodeItem(arena, crl, crlTemplate, crl->derCrl); - if (rv != SECSuccess) { - extended->badDER = PR_TRUE; - break; - } - /* check for critical extensions */ - rv = cert_check_crl_version (&crl->crl); - if (rv != SECSuccess) { - extended->badExtensions = PR_TRUE; - break; - } - - if (PR_TRUE == extended->partial) { - /* partial decoding, don't verify entries */ - break; - } - - rv = cert_check_crl_entries(&crl->crl); - if (rv != SECSuccess) { - extended->badExtensions = PR_TRUE; - } - - break; - - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; - break; - } - - if (rv != SECSuccess) { - goto loser; - } - - crl->referenceCount = 1; - - return(crl); - -loser: - if (options & CRL_DECODE_KEEP_BAD_CRL) { - if (extended) { - extended->decodingError = PR_TRUE; - } - if (crl) { - crl->referenceCount = 1; - return(crl); - } - } - - if ((narena == NULL) && arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(0); -} - -/* - * take a DER CRL and decode it into a CRL structure - */ -CERTSignedCrl * -CERT_DecodeDERCrl(PRArenaPool *narena, SECItem *derSignedCrl, int type) -{ - return CERT_DecodeDERCrlWithFlags(narena, derSignedCrl, type, - CRL_DECODE_DEFAULT_OPTIONS); -} - -/* - * Lookup a CRL in the databases. We mirror the same fast caching data base - * caching stuff used by certificates....? - * return values : - * - * SECSuccess means we got a valid decodable DER CRL, or no CRL at all. - * Caller may distinguish those cases by the value returned in "decoded". - * When DER CRL is not found, error code will be SEC_ERROR_CRL_NOT_FOUND. - * - * SECFailure means we got a fatal error - most likely, we found a CRL, - * and it failed decoding, or there was an out of memory error. Do NOT ignore - * it and specifically do NOT treat it the same as having no CRL, as this - * can compromise security !!! Ideally, you should treat this case as if you - * received a "catch-all" CRL where all certs you were looking up are - * considered to be revoked - */ -static SECStatus -SEC_FindCrlByKeyOnSlot(PK11SlotInfo *slot, SECItem *crlKey, int type, - CERTSignedCrl** decoded, PRInt32 decodeoptions) -{ - SECStatus rv = SECSuccess; - CERTSignedCrl *crl = NULL; - SECItem *derCrl = NULL; - CK_OBJECT_HANDLE crlHandle = 0; - char *url = NULL; - - PORT_Assert(decoded); - if (!decoded) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - derCrl = PK11_FindCrlByName(&slot, &crlHandle, crlKey, type, &url); - if (derCrl == NULL) { - /* if we had a problem other than the CRL just didn't exist, return - * a failure to the upper level */ - int nsserror = PORT_GetError(); - if (nsserror != SEC_ERROR_CRL_NOT_FOUND) { - rv = SECFailure; - } - goto loser; - } - PORT_Assert(crlHandle != CK_INVALID_HANDLE); - /* PK11_FindCrlByName obtained a slot reference. */ - - /* derCRL is a fresh HEAP copy made for us by PK11_FindCrlByName. - Force adoption of the DER CRL from the heap - this will cause it - to be automatically freed when SEC_DestroyCrl is invoked */ - decodeoptions |= (CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_DONT_COPY_DER); - - crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl, type, decodeoptions); - if (crl) { - crl->slot = slot; - slot = NULL; /* adopt it */ - derCrl = NULL; /* adopted by the crl struct */ - crl->pkcs11ID = crlHandle; - if (url) { - crl->url = PORT_ArenaStrdup(crl->arena,url); - } - } else { - rv = SECFailure; - } - - if (url) { - PORT_Free(url); - } - - if (slot) { - PK11_FreeSlot(slot); - } - -loser: - if (derCrl) { - SECITEM_FreeItem(derCrl, PR_TRUE); - } - - *decoded = crl; - - return rv; -} - - -CERTSignedCrl * -crl_storeCRL (PK11SlotInfo *slot,char *url, - CERTSignedCrl *newCrl, SECItem *derCrl, int type) -{ - CERTSignedCrl *oldCrl = NULL, *crl = NULL; - PRBool deleteOldCrl = PR_FALSE; - CK_OBJECT_HANDLE crlHandle = CK_INVALID_HANDLE; - SECStatus rv; - - PORT_Assert(newCrl); - PORT_Assert(derCrl); - PORT_Assert(type == SEC_CRL_TYPE); - - if (type != SEC_CRL_TYPE) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - - /* we can't use the cache here because we must look in the same - token */ - rv = SEC_FindCrlByKeyOnSlot(slot, &newCrl->crl.derName, type, - &oldCrl, CRL_DECODE_SKIP_ENTRIES); - /* if there is an old crl on the token, make sure the one we are - installing is newer. If not, exit out, otherwise delete the - old crl. - */ - if (oldCrl != NULL) { - /* if it's already there, quietly continue */ - if (SECITEM_CompareItem(newCrl->derCrl, oldCrl->derCrl) - == SECEqual) { - crl = newCrl; - crl->slot = PK11_ReferenceSlot(slot); - crl->pkcs11ID = oldCrl->pkcs11ID; - if (oldCrl->url && !url) - url = oldCrl->url; - if (url) - crl->url = PORT_ArenaStrdup(crl->arena, url); - goto done; - } - if (!SEC_CrlIsNewer(&newCrl->crl,&oldCrl->crl)) { - PORT_SetError(SEC_ERROR_OLD_CRL); - goto done; - } - - /* if we have a url in the database, use that one */ - if (oldCrl->url && !url) { - url = oldCrl->url; - } - - /* really destroy this crl */ - /* first drum it out of the permanment Data base */ - deleteOldCrl = PR_TRUE; - } - - /* invalidate CRL cache for this issuer */ - CERT_CRLCacheRefreshIssuer(NULL, &newCrl->crl.derName); - /* Write the new entry into the data base */ - crlHandle = PK11_PutCrl(slot, derCrl, &newCrl->crl.derName, url, type); - if (crlHandle != CK_INVALID_HANDLE) { - crl = newCrl; - crl->slot = PK11_ReferenceSlot(slot); - crl->pkcs11ID = crlHandle; - if (url) { - crl->url = PORT_ArenaStrdup(crl->arena,url); - } - } - -done: - if (oldCrl) { - if (deleteOldCrl && crlHandle != CK_INVALID_HANDLE) { - SEC_DeletePermCRL(oldCrl); - } - SEC_DestroyCrl(oldCrl); - } - - return crl; -} - -/* - * - * create a new CRL from DER material. - * - * The signature on this CRL must be checked before you - * load it. ??? - */ -CERTSignedCrl * -SEC_NewCrl(CERTCertDBHandle *handle, char *url, SECItem *derCrl, int type) -{ - CERTSignedCrl* retCrl = NULL; - PK11SlotInfo* slot = PK11_GetInternalKeySlot(); - retCrl = PK11_ImportCRL(slot, derCrl, url, type, NULL, - CRL_IMPORT_BYPASS_CHECKS, NULL, CRL_DECODE_DEFAULT_OPTIONS); - PK11_FreeSlot(slot); - - return retCrl; -} - -CERTSignedCrl * -SEC_FindCrlByDERCert(CERTCertDBHandle *handle, SECItem *derCrl, int type) -{ - PRArenaPool *arena; - SECItem crlKey; - SECStatus rv; - CERTSignedCrl *crl = NULL; - - /* create a scratch arena */ - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - return(NULL); - } - - /* extract the database key from the cert */ - rv = CERT_KeyFromDERCrl(arena, derCrl, &crlKey); - if ( rv != SECSuccess ) { - goto loser; - } - - /* find the crl */ - crl = SEC_FindCrlByName(handle, &crlKey, type); - -loser: - PORT_FreeArena(arena, PR_FALSE); - return(crl); -} - -CERTSignedCrl* SEC_DupCrl(CERTSignedCrl* acrl) -{ - if (acrl) - { - PR_ATOMIC_INCREMENT(&acrl->referenceCount); - return acrl; - } - return NULL; -} - -SECStatus -SEC_DestroyCrl(CERTSignedCrl *crl) -{ - if (crl) { - if (PR_ATOMIC_DECREMENT(&crl->referenceCount) < 1) { - if (crl->slot) { - PK11_FreeSlot(crl->slot); - } - if (GetOpaqueCRLFields(crl) && - PR_TRUE == GetOpaqueCRLFields(crl)->heapDER) { - SECITEM_FreeItem(crl->derCrl, PR_TRUE); - } - if (crl->arena) { - PORT_FreeArena(crl->arena, PR_FALSE); - } - } - return SECSuccess; - } else { - return SECFailure; - } -} - -SECStatus -SEC_LookupCrls(CERTCertDBHandle *handle, CERTCrlHeadNode **nodes, int type) -{ - CERTCrlHeadNode *head; - PRArenaPool *arena = NULL; - SECStatus rv; - - *nodes = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - return SECFailure; - } - - /* build a head structure */ - head = (CERTCrlHeadNode *)PORT_ArenaAlloc(arena, sizeof(CERTCrlHeadNode)); - head->arena = arena; - head->first = NULL; - head->last = NULL; - head->dbhandle = handle; - - /* Look up the proper crl types */ - *nodes = head; - - rv = PK11_LookupCrls(head, type, NULL); - - if (rv != SECSuccess) { - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - *nodes = NULL; - } - } - - return rv; -} - -/* These functions simply return the address of the above-declared templates. -** This is necessary for Windows DLLs. Sigh. -*/ -SEC_ASN1_CHOOSER_IMPLEMENT(CERT_IssuerAndSNTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CrlTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SignedCrlTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SetOfSignedCrlTemplate) - -/* CRL cache code starts here */ - -/* constructor */ -static SECStatus CachedCrl_Create(CachedCrl** returned, CERTSignedCrl* crl, - CRLOrigin origin); -/* destructor */ -static SECStatus CachedCrl_Destroy(CachedCrl* crl); - -/* create hash table of CRL entries */ -static SECStatus CachedCrl_Populate(CachedCrl* crlobject); - -/* empty the cache content */ -static SECStatus CachedCrl_Depopulate(CachedCrl* crl); - -/* are these CRLs the same, as far as the cache is concerned ? - Or are they the same token object, but with different DER ? */ - -static SECStatus CachedCrl_Compare(CachedCrl* a, CachedCrl* b, PRBool* isDupe, - PRBool* isUpdated); - -/* create a DPCache object */ -static SECStatus DPCache_Create(CRLDPCache** returned, CERTCertificate* issuer, - const SECItem* subject, SECItem* dp); - -/* destructor for CRL DPCache object */ -static SECStatus DPCache_Destroy(CRLDPCache* cache); - -/* add a new CRL object to the dynamic array of CRLs of the DPCache, and - returns the cached CRL object . Needs write access to DPCache. */ -static SECStatus DPCache_AddCRL(CRLDPCache* cache, CachedCrl* crl, - PRBool* added); - -/* fetch the CRL for this DP from the PKCS#11 tokens */ -static SECStatus DPCache_FetchFromTokens(CRLDPCache* cache, PRTime vfdate, - void* wincx); - -/* update the content of the CRL cache, including fetching of CRLs, and - reprocessing with specified issuer and date */ -static SECStatus DPCache_GetUpToDate(CRLDPCache* cache, CERTCertificate* issuer, - PRBool readlocked, PRTime vfdate, void* wincx); - -/* returns true if there are CRLs from PKCS#11 slots */ -static PRBool DPCache_HasTokenCRLs(CRLDPCache* cache); - -/* remove CRL at offset specified */ -static SECStatus DPCache_RemoveCRL(CRLDPCache* cache, PRUint32 offset); - -/* Pick best CRL to use . needs write access */ -static SECStatus DPCache_SelectCRL(CRLDPCache* cache); - -/* create an issuer cache object (per CA subject ) */ -static SECStatus IssuerCache_Create(CRLIssuerCache** returned, - CERTCertificate* issuer, - const SECItem* subject, const SECItem* dp); - -/* destructor for CRL IssuerCache object */ -SECStatus IssuerCache_Destroy(CRLIssuerCache* cache); - -/* add a DPCache to the issuer cache */ -static SECStatus IssuerCache_AddDP(CRLIssuerCache* cache, - CERTCertificate* issuer, - const SECItem* subject, - const SECItem* dp, CRLDPCache** newdpc); - -/* get a particular DPCache object from an IssuerCache */ -static CRLDPCache* IssuerCache_GetDPCache(CRLIssuerCache* cache, - const SECItem* dp); - -/* -** Pre-allocator hash allocator ops. -*/ - -/* allocate memory for hash table */ -static void * PR_CALLBACK -PreAllocTable(void *pool, PRSize size) -{ - PreAllocator* alloc = (PreAllocator*)pool; - PORT_Assert(alloc); - if (!alloc) - { - /* no allocator, or buffer full */ - return NULL; - } - if (size > (alloc->len - alloc->used)) - { - /* initial buffer full, let's use the arena */ - alloc->extra += size; - return PORT_ArenaAlloc(alloc->arena, size); - } - /* use the initial buffer */ - alloc->used += size; - return (char*) alloc->data + alloc->used - size; -} - -/* free hash table memory. - Individual PreAllocator elements cannot be freed, so this is a no-op. */ -static void PR_CALLBACK -PreFreeTable(void *pool, void *item) -{ -} - -/* allocate memory for hash table */ -static PLHashEntry * PR_CALLBACK -PreAllocEntry(void *pool, const void *key) -{ - return PreAllocTable(pool, sizeof(PLHashEntry)); -} - -/* free hash table entry. - Individual PreAllocator elements cannot be freed, so this is a no-op. */ -static void PR_CALLBACK -PreFreeEntry(void *pool, PLHashEntry *he, PRUintn flag) -{ -} - -/* methods required for PL hash table functions */ -static PLHashAllocOps preAllocOps = -{ - PreAllocTable, PreFreeTable, - PreAllocEntry, PreFreeEntry -}; - -/* destructor for PreAllocator object */ -void PreAllocator_Destroy(PreAllocator* PreAllocator) -{ - if (!PreAllocator) - { - return; - } - if (PreAllocator->arena) - { - PORT_FreeArena(PreAllocator->arena, PR_TRUE); - } -} - -/* constructor for PreAllocator object */ -PreAllocator* PreAllocator_Create(PRSize size) -{ - PRArenaPool* arena = NULL; - PreAllocator* prebuffer = NULL; - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (!arena) - { - return NULL; - } - prebuffer = (PreAllocator*)PORT_ArenaZAlloc(arena, - sizeof(PreAllocator)); - if (!prebuffer) - { - PORT_FreeArena(arena, PR_TRUE); - return NULL; - } - prebuffer->arena = arena; - - if (size) - { - prebuffer->len = size; - prebuffer->data = PORT_ArenaAlloc(arena, size); - if (!prebuffer->data) - { - PORT_FreeArena(arena, PR_TRUE); - return NULL; - } - } - return prebuffer; -} - -/* global Named CRL cache object */ -static NamedCRLCache namedCRLCache = { NULL, NULL }; - -/* global CRL cache object */ -static CRLCache crlcache = { NULL, NULL }; - -/* initial state is off */ -static PRBool crlcache_initialized = PR_FALSE; - -PRTime CRLCache_Empty_TokenFetch_Interval = 60 * 1000000; /* how often - to query the tokens for CRL objects, in order to discover new objects, if - the cache does not contain any token CRLs . In microseconds */ - -PRTime CRLCache_TokenRefetch_Interval = 600 * 1000000 ; /* how often - to query the tokens for CRL objects, in order to discover new objects, if - the cache already contains token CRLs In microseconds */ - -PRTime CRLCache_ExistenceCheck_Interval = 60 * 1000000; /* how often to check - if a token CRL object still exists. In microseconds */ - -/* this function is called at NSS initialization time */ -SECStatus InitCRLCache(void) -{ - if (PR_FALSE == crlcache_initialized) - { - PORT_Assert(NULL == crlcache.lock); - PORT_Assert(NULL == crlcache.issuers); - PORT_Assert(NULL == namedCRLCache.lock); - PORT_Assert(NULL == namedCRLCache.entries); - if (crlcache.lock || crlcache.issuers || namedCRLCache.lock || - namedCRLCache.entries) - { - /* CRL cache already partially initialized */ - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } -#ifdef GLOBAL_RWLOCK - crlcache.lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL); -#else - crlcache.lock = PR_NewLock(); -#endif - namedCRLCache.lock = PR_NewLock(); - crlcache.issuers = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, - PL_CompareValues, NULL, NULL); - namedCRLCache.entries = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, - PL_CompareValues, NULL, NULL); - if (!crlcache.lock || !namedCRLCache.lock || !crlcache.issuers || - !namedCRLCache.entries) - { - if (crlcache.lock) - { -#ifdef GLOBAL_RWLOCK - NSSRWLock_Destroy(crlcache.lock); -#else - PR_DestroyLock(crlcache.lock); -#endif - crlcache.lock = NULL; - } - if (namedCRLCache.lock) - { - PR_DestroyLock(namedCRLCache.lock); - namedCRLCache.lock = NULL; - } - if (crlcache.issuers) - { - PL_HashTableDestroy(crlcache.issuers); - crlcache.issuers = NULL; - } - if (namedCRLCache.entries) - { - PL_HashTableDestroy(namedCRLCache.entries); - namedCRLCache.entries = NULL; - } - - return SECFailure; - } - crlcache_initialized = PR_TRUE; - return SECSuccess; - } - else - { - PORT_Assert(crlcache.lock); - PORT_Assert(crlcache.issuers); - if ( (NULL == crlcache.lock) || (NULL == crlcache.issuers) ) - { - /* CRL cache not fully initialized */ - return SECFailure; - } - else - { - /* CRL cache already initialized */ - return SECSuccess; - } - } -} - -/* destructor for CRL DPCache object */ -static SECStatus DPCache_Destroy(CRLDPCache* cache) -{ - PRUint32 i = 0; - PORT_Assert(cache); - if (!cache) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - if (cache->lock) - { -#ifdef DPC_RWLOCK - NSSRWLock_Destroy(cache->lock); -#else - PR_DestroyLock(cache->lock); -#endif - } - else - { - PORT_Assert(0); - return SECFailure; - } - /* destroy all our CRL objects */ - for (i=0;i<cache->ncrls;i++) - { - if (!cache->crls || !cache->crls[i] || - SECSuccess != CachedCrl_Destroy(cache->crls[i])) - { - return SECFailure; - } - } - /* free the array of CRLs */ - if (cache->crls) - { - PORT_Free(cache->crls); - } - /* destroy the cert */ - if (cache->issuer) - { - CERT_DestroyCertificate(cache->issuer); - } - /* free the subject */ - if (cache->subject) - { - SECITEM_FreeItem(cache->subject, PR_TRUE); - } - /* free the distribution points */ - if (cache->distributionPoint) - { - SECITEM_FreeItem(cache->distributionPoint, PR_TRUE); - } - PORT_Free(cache); - return SECSuccess; -} - -/* destructor for CRL IssuerCache object */ -SECStatus IssuerCache_Destroy(CRLIssuerCache* cache) -{ - PORT_Assert(cache); - if (!cache) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } -#ifdef XCRL - if (cache->lock) - { - NSSRWLock_Destroy(cache->lock); - } - else - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - if (cache->issuer) - { - CERT_DestroyCertificate(cache->issuer); - } -#endif - /* free the subject */ - if (cache->subject) - { - SECITEM_FreeItem(cache->subject, PR_TRUE); - } - if (SECSuccess != DPCache_Destroy(cache->dpp)) - { - PORT_Assert(0); - return SECFailure; - } - PORT_Free(cache); - return SECSuccess; -} - -/* create a named CRL entry object */ -static SECStatus NamedCRLCacheEntry_Create(NamedCRLCacheEntry** returned) -{ - NamedCRLCacheEntry* entry = NULL; - if (!returned) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - *returned = NULL; - entry = (NamedCRLCacheEntry*) PORT_ZAlloc(sizeof(NamedCRLCacheEntry)); - if (!entry) - { - return SECFailure; - } - *returned = entry; - return SECSuccess; -} - -/* destroy a named CRL entry object */ -static SECStatus NamedCRLCacheEntry_Destroy(NamedCRLCacheEntry* entry) -{ - if (!entry) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - if (entry->crl) - { - /* named CRL cache owns DER memory */ - SECITEM_ZfreeItem(entry->crl, PR_TRUE); - } - if (entry->canonicalizedName) - { - SECITEM_FreeItem(entry->canonicalizedName, PR_TRUE); - } - PORT_Free(entry); - return SECSuccess; -} - -/* callback function used in hash table destructor */ -static PRIntn PR_CALLBACK FreeIssuer(PLHashEntry *he, PRIntn i, void *arg) -{ - CRLIssuerCache* issuer = NULL; - SECStatus* rv = (SECStatus*) arg; - - PORT_Assert(he); - if (!he) - { - return HT_ENUMERATE_NEXT; - } - issuer = (CRLIssuerCache*) he->value; - PORT_Assert(issuer); - if (issuer) - { - if (SECSuccess != IssuerCache_Destroy(issuer)) - { - PORT_Assert(rv); - if (rv) - { - *rv = SECFailure; - } - return HT_ENUMERATE_NEXT; - } - } - return HT_ENUMERATE_NEXT; -} - -/* callback function used in hash table destructor */ -static PRIntn PR_CALLBACK FreeNamedEntries(PLHashEntry *he, PRIntn i, void *arg) -{ - NamedCRLCacheEntry* entry = NULL; - SECStatus* rv = (SECStatus*) arg; - - PORT_Assert(he); - if (!he) - { - return HT_ENUMERATE_NEXT; - } - entry = (NamedCRLCacheEntry*) he->value; - PORT_Assert(entry); - if (entry) - { - if (SECSuccess != NamedCRLCacheEntry_Destroy(entry)) - { - PORT_Assert(rv); - if (rv) - { - *rv = SECFailure; - } - return HT_ENUMERATE_NEXT; - } - } - return HT_ENUMERATE_NEXT; -} - -/* needs to be called at NSS shutdown time - This will destroy the global CRL cache, including - - the hash table of issuer cache objects - - the issuer cache objects - - DPCache objects in issuer cache objects */ -SECStatus ShutdownCRLCache(void) -{ - SECStatus rv = SECSuccess; - if (PR_FALSE == crlcache_initialized && - !crlcache.lock && !crlcache.issuers) - { - /* CRL cache has already been shut down */ - return SECSuccess; - } - if (PR_TRUE == crlcache_initialized && - (!crlcache.lock || !crlcache.issuers || !namedCRLCache.lock || - !namedCRLCache.entries)) - { - /* CRL cache has partially been shut down */ - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - /* empty the CRL cache */ - /* free the issuers */ - PL_HashTableEnumerateEntries(crlcache.issuers, &FreeIssuer, &rv); - /* free the hash table of issuers */ - PL_HashTableDestroy(crlcache.issuers); - crlcache.issuers = NULL; - /* free the global lock */ -#ifdef GLOBAL_RWLOCK - NSSRWLock_Destroy(crlcache.lock); -#else - PR_DestroyLock(crlcache.lock); -#endif - crlcache.lock = NULL; - - /* empty the named CRL cache. This must be done after freeing the CRL - * cache, since some CRLs in this cache are in the memory for the other */ - /* free the entries */ - PL_HashTableEnumerateEntries(namedCRLCache.entries, &FreeNamedEntries, &rv); - /* free the hash table of issuers */ - PL_HashTableDestroy(namedCRLCache.entries); - namedCRLCache.entries = NULL; - /* free the global lock */ - PR_DestroyLock(namedCRLCache.lock); - namedCRLCache.lock = NULL; - - crlcache_initialized = PR_FALSE; - return rv; -} - -/* add a new CRL object to the dynamic array of CRLs of the DPCache, and - returns the cached CRL object . Needs write access to DPCache. */ -static SECStatus DPCache_AddCRL(CRLDPCache* cache, CachedCrl* newcrl, - PRBool* added) -{ - CachedCrl** newcrls = NULL; - PRUint32 i = 0; - PORT_Assert(cache); - PORT_Assert(newcrl); - PORT_Assert(added); - if (!cache || !newcrl || !added) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - - *added = PR_FALSE; - /* before adding a new CRL, check if it is a duplicate */ - for (i=0;i<cache->ncrls;i++) - { - CachedCrl* existing = NULL; - SECStatus rv = SECSuccess; - PRBool dupe = PR_FALSE, updated = PR_FALSE; - if (!cache->crls) - { - PORT_Assert(0); - return SECFailure; - } - existing = cache->crls[i]; - if (!existing) - { - PORT_Assert(0); - return SECFailure; - } - rv = CachedCrl_Compare(existing, newcrl, &dupe, &updated); - if (SECSuccess != rv) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - if (PR_TRUE == dupe) - { - /* dupe */ - PORT_SetError(SEC_ERROR_CRL_ALREADY_EXISTS); - return SECSuccess; - } - if (PR_TRUE == updated) - { - /* this token CRL is in the same slot and has the same object ID, - but different content. We need to remove the old object */ - if (SECSuccess != DPCache_RemoveCRL(cache, i)) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return PR_FALSE; - } - } - } - - newcrls = (CachedCrl**)PORT_Realloc(cache->crls, - (cache->ncrls+1)*sizeof(CachedCrl*)); - if (!newcrls) - { - return SECFailure; - } - cache->crls = newcrls; - cache->ncrls++; - cache->crls[cache->ncrls-1] = newcrl; - *added = PR_TRUE; - return SECSuccess; -} - -/* remove CRL at offset specified */ -static SECStatus DPCache_RemoveCRL(CRLDPCache* cache, PRUint32 offset) -{ - CachedCrl* acrl = NULL; - PORT_Assert(cache); - if (!cache || (!cache->crls) || (!(offset<cache->ncrls)) ) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - acrl = cache->crls[offset]; - PORT_Assert(acrl); - if (!acrl) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - cache->crls[offset] = cache->crls[cache->ncrls-1]; - cache->crls[cache->ncrls-1] = NULL; - cache->ncrls--; - if (cache->selected == acrl) { - cache->selected = NULL; - } - if (SECSuccess != CachedCrl_Destroy(acrl)) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - return SECSuccess; -} - -/* check whether a CRL object stored in a PKCS#11 token still exists in - that token . This has to be efficient (the entire CRL value cannot be - transferred accross the token boundaries), so this is accomplished by - simply fetching the subject attribute and making sure it hasn't changed . - Note that technically, the CRL object could have been replaced with a new - PKCS#11 object of the same ID and subject (which actually happens in - softoken), but this function has no way of knowing that the object - value changed, since CKA_VALUE isn't checked. */ -static PRBool TokenCRLStillExists(CERTSignedCrl* crl) -{ - NSSItem newsubject; - SECItem subject; - CK_ULONG crl_class; - PRStatus status; - PK11SlotInfo* slot = NULL; - nssCryptokiObject instance; - NSSArena* arena; - PRBool xstatus = PR_TRUE; - SECItem* oldSubject = NULL; - - PORT_Assert(crl); - if (!crl) - { - return PR_FALSE; - } - slot = crl->slot; - PORT_Assert(crl->slot); - if (!slot) - { - return PR_FALSE; - } - oldSubject = &crl->crl.derName; - PORT_Assert(oldSubject); - if (!oldSubject) - { - return PR_FALSE; - } - - /* query subject and type attributes in order to determine if the - object has been deleted */ - - /* first, make an nssCryptokiObject */ - instance.handle = crl->pkcs11ID; - PORT_Assert(instance.handle); - if (!instance.handle) - { - return PR_FALSE; - } - instance.token = PK11Slot_GetNSSToken(slot); - PORT_Assert(instance.token); - if (!instance.token) - { - return PR_FALSE; - } - instance.isTokenObject = PR_TRUE; - instance.label = NULL; - - arena = NSSArena_Create(); - PORT_Assert(arena); - if (!arena) - { - return PR_FALSE; - } - - status = nssCryptokiCRL_GetAttributes(&instance, - NULL, /* XXX sessionOpt */ - arena, - NULL, - &newsubject, /* subject */ - &crl_class, /* class */ - NULL, - NULL); - if (PR_SUCCESS == status) - { - subject.data = newsubject.data; - subject.len = newsubject.size; - if (SECITEM_CompareItem(oldSubject, &subject) != SECEqual) - { - xstatus = PR_FALSE; - } - if (CKO_NETSCAPE_CRL != crl_class) - { - xstatus = PR_FALSE; - } - } - else - { - xstatus = PR_FALSE; - } - NSSArena_Destroy(arena); - return xstatus; -} - -/* verify the signature of a CRL against its issuer at a given date */ -static SECStatus CERT_VerifyCRL( - CERTSignedCrl* crlobject, - CERTCertificate* issuer, - PRTime vfdate, - void* wincx) -{ - return CERT_VerifySignedData(&crlobject->signatureWrap, - issuer, vfdate, wincx); -} - -/* verify a CRL and update cache state */ -static SECStatus CachedCrl_Verify(CRLDPCache* cache, CachedCrl* crlobject, - PRTime vfdate, void* wincx) -{ - /* Check if it is an invalid CRL - if we got a bad CRL, we want to cache it in order to avoid - subsequent fetches of this same identical bad CRL. We set - the cache to the invalid state to ensure that all certs on this - DP are considered to have unknown status from now on. The cache - object will remain in this state until the bad CRL object - is removed from the token it was fetched from. If the cause - of the failure is that we didn't have the issuer cert to - verify the signature, this state can be cleared when - the issuer certificate becomes available if that causes the - signature to verify */ - - if (!cache || !crlobject) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - if (PR_TRUE == GetOpaqueCRLFields(crlobject->crl)->decodingError) - { - crlobject->sigChecked = PR_TRUE; /* we can never verify a CRL - with bogus DER. Mark it checked so we won't try again */ - PORT_SetError(SEC_ERROR_BAD_DER); - return SECSuccess; - } - else - { - SECStatus signstatus = SECFailure; - if (cache->issuer) - { - signstatus = CERT_VerifyCRL(crlobject->crl, cache->issuer, vfdate, - wincx); - } - if (SECSuccess != signstatus) - { - if (!cache->issuer) - { - /* we tried to verify without an issuer cert . This is - because this CRL came through a call to SEC_FindCrlByName. - So, we don't cache this verification failure. We'll try - to verify the CRL again when a certificate from that issuer - becomes available */ - } else - { - crlobject->sigChecked = PR_TRUE; - } - PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE); - return SECSuccess; - } else - { - crlobject->sigChecked = PR_TRUE; - crlobject->sigValid = PR_TRUE; - } - } - - return SECSuccess; -} - -/* fetch the CRLs for this DP from the PKCS#11 tokens */ -static SECStatus DPCache_FetchFromTokens(CRLDPCache* cache, PRTime vfdate, - void* wincx) -{ - SECStatus rv = SECSuccess; - CERTCrlHeadNode head; - if (!cache) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - /* first, initialize list */ - memset(&head, 0, sizeof(head)); - head.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - rv = pk11_RetrieveCrls(&head, cache->subject, wincx); - - /* if this function fails, something very wrong happened, such as an out - of memory error during CRL decoding. We don't want to proceed and must - mark the cache object invalid */ - if (SECFailure == rv) - { - /* fetch failed, add error bit */ - cache->invalid |= CRL_CACHE_LAST_FETCH_FAILED; - } else - { - /* fetch was successful, clear this error bit */ - cache->invalid &= (~CRL_CACHE_LAST_FETCH_FAILED); - } - - /* add any CRLs found to our array */ - if (SECSuccess == rv) - { - CERTCrlNode* crlNode = NULL; - - for (crlNode = head.first; crlNode ; crlNode = crlNode->next) - { - CachedCrl* returned = NULL; - CERTSignedCrl* crlobject = crlNode->crl; - if (!crlobject) - { - PORT_Assert(0); - continue; - } - rv = CachedCrl_Create(&returned, crlobject, CRL_OriginToken); - if (SECSuccess == rv) - { - PRBool added = PR_FALSE; - rv = DPCache_AddCRL(cache, returned, &added); - if (PR_TRUE != added) - { - rv = CachedCrl_Destroy(returned); - returned = NULL; - } - else if (vfdate) - { - rv = CachedCrl_Verify(cache, returned, vfdate, wincx); - } - } - else - { - /* not enough memory to add the CRL to the cache. mark it - invalid so we will try again . */ - cache->invalid |= CRL_CACHE_LAST_FETCH_FAILED; - } - if (SECFailure == rv) - { - break; - } - } - } - - if (head.arena) - { - CERTCrlNode* crlNode = NULL; - /* clean up the CRL list in case we got a partial one - during a failed fetch */ - for (crlNode = head.first; crlNode ; crlNode = crlNode->next) - { - if (crlNode->crl) - { - SEC_DestroyCrl(crlNode->crl); /* free the CRL. Either it got - added to the cache and the refcount got bumped, or not, and - thus we need to free its RAM */ - } - } - PORT_FreeArena(head.arena, PR_FALSE); /* destroy CRL list */ - } - - return rv; -} - -static SECStatus CachedCrl_GetEntry(CachedCrl* crl, SECItem* sn, - CERTCrlEntry** returned) -{ - CERTCrlEntry* acrlEntry; - - PORT_Assert(crl); - PORT_Assert(crl->entries); - PORT_Assert(sn); - PORT_Assert(returned); - if (!crl || !sn || !returned || !crl->entries) - { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - acrlEntry = PL_HashTableLookup(crl->entries, (void*)sn); - if (acrlEntry) - { - *returned = acrlEntry; - } - else - { - *returned = NULL; - } - return SECSuccess; -} - -/* check if a particular SN is in the CRL cache and return its entry */ -dpcacheStatus DPCache_Lookup(CRLDPCache* cache, SECItem* sn, - CERTCrlEntry** returned) -{ - SECStatus rv; - if (!cache || !sn || !returned) - { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - /* no cache or SN to look up, or no way to return entry */ - return dpcacheCallerError; - } - *returned = NULL; - if (0 != cache->invalid) - { - /* the cache contains a bad CRL, or there was a CRL fetching error. */ - PORT_SetError(SEC_ERROR_CRL_INVALID); - return dpcacheInvalidCacheError; - } - if (!cache->selected) - { - /* no CRL means no entry to return. This is OK, except for - * NIST policy */ - return dpcacheEmpty; - } - rv = CachedCrl_GetEntry(cache->selected, sn, returned); - if (SECSuccess != rv) - { - return dpcacheLookupError; - } - else - { - if (*returned) - { - return dpcacheFoundEntry; - } - else - { - return dpcacheNoEntry; - } - } -} - -#if defined(DPC_RWLOCK) - -#define DPCache_LockWrite() \ -{ \ - if (readlocked) \ - { \ - NSSRWLock_UnlockRead(cache->lock); \ - } \ - NSSRWLock_LockWrite(cache->lock); \ -} - -#define DPCache_UnlockWrite() \ -{ \ - if (readlocked) \ - { \ - NSSRWLock_LockRead(cache->lock); \ - } \ - NSSRWLock_UnlockWrite(cache->lock); \ -} - -#else - -/* with a global lock, we are always locked for read before we need write - access, so do nothing */ - -#define DPCache_LockWrite() \ -{ \ -} - -#define DPCache_UnlockWrite() \ -{ \ -} - -#endif - -/* update the content of the CRL cache, including fetching of CRLs, and - reprocessing with specified issuer and date . We are always holding - either the read or write lock on DPCache upon entry. */ -static SECStatus DPCache_GetUpToDate(CRLDPCache* cache, CERTCertificate* - issuer, PRBool readlocked, PRTime vfdate, - void* wincx) -{ - /* Update the CRLDPCache now. We don't cache token CRL lookup misses - yet, as we have no way of getting notified of new PKCS#11 object - creation that happens in a token */ - SECStatus rv = SECSuccess; - PRUint32 i = 0; - PRBool forcedrefresh = PR_FALSE; - PRBool dirty = PR_FALSE; /* whether something was changed in the - cache state during this update cycle */ - PRBool hastokenCRLs = PR_FALSE; - PRTime now = 0; - PRTime lastfetch = 0; - PRBool mustunlock = PR_FALSE; - - if (!cache) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - - /* first, make sure we have obtained all the CRLs we need. - We do an expensive token fetch in the following cases : - 1) cache is empty because no fetch was ever performed yet - 2) cache is explicitly set to refresh state - 3) cache is in invalid state because last fetch failed - 4) cache contains no token CRLs, and it's been more than one minute - since the last fetch - 5) cache contains token CRLs, and it's been more than 10 minutes since - the last fetch - */ - forcedrefresh = cache->refresh; - lastfetch = cache->lastfetch; - if (PR_TRUE != forcedrefresh && - (!(cache->invalid & CRL_CACHE_LAST_FETCH_FAILED))) - { - now = PR_Now(); - hastokenCRLs = DPCache_HasTokenCRLs(cache); - } - if ( (0 == lastfetch) || - - (PR_TRUE == forcedrefresh) || - - (cache->invalid & CRL_CACHE_LAST_FETCH_FAILED) || - - ( (PR_FALSE == hastokenCRLs) && - ( (now - cache->lastfetch > CRLCache_Empty_TokenFetch_Interval) || - (now < cache->lastfetch)) ) || - - ( (PR_TRUE == hastokenCRLs) && - ((now - cache->lastfetch > CRLCache_TokenRefetch_Interval) || - (now < cache->lastfetch)) ) ) - { - /* the cache needs to be refreshed, and/or we had zero CRL for this - DP. Try to get one from PKCS#11 tokens */ - DPCache_LockWrite(); - /* check if another thread updated before us, and skip update if so */ - if (lastfetch == cache->lastfetch) - { - /* we are the first */ - rv = DPCache_FetchFromTokens(cache, vfdate, wincx); - if (PR_TRUE == cache->refresh) - { - cache->refresh = PR_FALSE; /* clear refresh state */ - } - dirty = PR_TRUE; - cache->lastfetch = PR_Now(); - } - DPCache_UnlockWrite(); - } - - /* now, make sure we have no extraneous CRLs (deleted token objects) - we'll do this inexpensive existence check either - 1) if there was a token object fetch - 2) every minute */ - if (( PR_TRUE != dirty) && (!now) ) - { - now = PR_Now(); - } - if ( (PR_TRUE == dirty) || - ( (now - cache->lastcheck > CRLCache_ExistenceCheck_Interval) || - (now < cache->lastcheck)) ) - { - PRTime lastcheck = cache->lastcheck; - mustunlock = PR_FALSE; - /* check if all CRLs still exist */ - for (i = 0; (i < cache->ncrls) ; i++) - { - CachedCrl* savcrl = cache->crls[i]; - if ( (!savcrl) || (savcrl && CRL_OriginToken != savcrl->origin)) - { - /* we only want to check token CRLs */ - continue; - } - if ((PR_TRUE != TokenCRLStillExists(savcrl->crl))) - { - - /* this CRL is gone */ - if (PR_TRUE != mustunlock) - { - DPCache_LockWrite(); - mustunlock = PR_TRUE; - } - /* first, we need to check if another thread did an update - before we did */ - if (lastcheck == cache->lastcheck) - { - /* the CRL is gone. And we are the one to do the update */ - DPCache_RemoveCRL(cache, i); - dirty = PR_TRUE; - } - /* stay locked here intentionally so we do all the other - updates in this thread for the remaining CRLs */ - } - } - if (PR_TRUE == mustunlock) - { - cache->lastcheck = PR_Now(); - DPCache_UnlockWrite(); - mustunlock = PR_FALSE; - } - } - - /* add issuer certificate if it was previously unavailable */ - if (issuer && (NULL == cache->issuer) && - (SECSuccess == CERT_CheckCertUsage(issuer, KU_CRL_SIGN))) - { - /* if we didn't have a valid issuer cert yet, but we do now. add it */ - DPCache_LockWrite(); - if (!cache->issuer) - { - dirty = PR_TRUE; - cache->issuer = CERT_DupCertificate(issuer); - } - DPCache_UnlockWrite(); - } - - /* verify CRLs that couldn't be checked when inserted into the cache - because the issuer cert or a verification date was unavailable. - These are CRLs that were inserted into the cache through - SEC_FindCrlByName, or through manual insertion, rather than through a - certificate verification (CERT_CheckCRL) */ - - if (cache->issuer && vfdate ) - { - mustunlock = PR_FALSE; - /* re-process all unverified CRLs */ - for (i = 0; i < cache->ncrls ; i++) - { - CachedCrl* savcrl = cache->crls[i]; - if (!savcrl) - { - continue; - } - if (PR_TRUE != savcrl->sigChecked) - { - if (!mustunlock) - { - DPCache_LockWrite(); - mustunlock = PR_TRUE; - } - /* first, we need to check if another thread updated - it before we did, and abort if it has been modified since - we acquired the lock. Make sure first that the CRL is still - in the array at the same position */ - if ( (i<cache->ncrls) && (savcrl == cache->crls[i]) && - (PR_TRUE != savcrl->sigChecked) ) - { - /* the CRL is still there, unverified. Do it */ - CachedCrl_Verify(cache, savcrl, vfdate, wincx); - dirty = PR_TRUE; - } - /* stay locked here intentionally so we do all the other - updates in this thread for the remaining CRLs */ - } - if (mustunlock && !dirty) - { - DPCache_UnlockWrite(); - mustunlock = PR_FALSE; - } - } - } - - if (dirty || cache->mustchoose) - { - /* changes to the content of the CRL cache necessitate examining all - CRLs for selection of the most appropriate one to cache */ - if (!mustunlock) - { - DPCache_LockWrite(); - mustunlock = PR_TRUE; - } - DPCache_SelectCRL(cache); - cache->mustchoose = PR_FALSE; - } - if (mustunlock) - DPCache_UnlockWrite(); - - return rv; -} - -/* callback for qsort to sort by thisUpdate */ -static int SortCRLsByThisUpdate(const void* arg1, const void* arg2) -{ - PRTime timea, timeb; - SECStatus rv = SECSuccess; - CachedCrl* a, *b; - - a = *(CachedCrl**) arg1; - b = *(CachedCrl**) arg2; - - if (!a || !b) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - rv = SECFailure; - } - - if (SECSuccess == rv) - { - rv = DER_DecodeTimeChoice(&timea, &a->crl->crl.lastUpdate); - } - if (SECSuccess == rv) - { - rv = DER_DecodeTimeChoice(&timeb, &b->crl->crl.lastUpdate); - } - if (SECSuccess == rv) - { - if (timea > timeb) - { - return 1; /* a is better than b */ - } - if (timea < timeb ) - { - return -1; /* a is not as good as b */ - } - } - - /* if they are equal, or if all else fails, use pointer differences */ - PORT_Assert(a != b); /* they should never be equal */ - return a>b?1:-1; -} - -/* callback for qsort to sort a set of disparate CRLs, some of which are - invalid DER or failed signature check. - - Validated CRLs are differentiated by thisUpdate . - Validated CRLs are preferred over non-validated CRLs . - Proper DER CRLs are preferred over non-DER data . -*/ -static int SortImperfectCRLs(const void* arg1, const void* arg2) -{ - CachedCrl* a, *b; - - a = *(CachedCrl**) arg1; - b = *(CachedCrl**) arg2; - - if (!a || !b) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - PORT_Assert(0); - } - else - { - PRBool aDecoded = PR_FALSE, bDecoded = PR_FALSE; - if ( (PR_TRUE == a->sigValid) && (PR_TRUE == b->sigValid) ) - { - /* both CRLs have been validated, choose the latest one */ - return SortCRLsByThisUpdate(arg1, arg2); - } - if (PR_TRUE == a->sigValid) - { - return 1; /* a is greater than b */ - } - if (PR_TRUE == b->sigValid) - { - return -1; /* a is not as good as b */ - } - aDecoded = GetOpaqueCRLFields(a->crl)->decodingError; - bDecoded = GetOpaqueCRLFields(b->crl)->decodingError; - /* neither CRL had its signature check pass */ - if ( (PR_FALSE == aDecoded) && (PR_FALSE == bDecoded) ) - { - /* both CRLs are proper DER, choose the latest one */ - return SortCRLsByThisUpdate(arg1, arg2); - } - if (PR_FALSE == aDecoded) - { - return 1; /* a is better than b */ - } - if (PR_FALSE == bDecoded) - { - return -1; /* a is not as good as b */ - } - /* both are invalid DER. sigh. */ - } - /* if they are equal, or if all else fails, use pointer differences */ - PORT_Assert(a != b); /* they should never be equal */ - return a>b?1:-1; -} - - -/* Pick best CRL to use . needs write access */ -static SECStatus DPCache_SelectCRL(CRLDPCache* cache) -{ - PRUint32 i; - PRBool valid = PR_TRUE; - CachedCrl* selected = NULL; - - PORT_Assert(cache); - if (!cache) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - /* if any invalid CRL is present, then the CRL cache is - considered invalid, for security reasons */ - for (i = 0 ; i<cache->ncrls; i++) - { - if (!cache->crls[i] || !cache->crls[i]->sigChecked || - !cache->crls[i]->sigValid) - { - valid = PR_FALSE; - break; - } - } - if (PR_TRUE == valid) - { - /* all CRLs are valid, clear this error */ - cache->invalid &= (~CRL_CACHE_INVALID_CRLS); - } else - { - /* some CRLs are invalid, set this error */ - cache->invalid |= CRL_CACHE_INVALID_CRLS; - } - - if (cache->invalid) - { - /* cache is in an invalid state, so reset it */ - if (cache->selected) - { - cache->selected = NULL; - } - /* also sort the CRLs imperfectly */ - qsort(cache->crls, cache->ncrls, sizeof(CachedCrl*), - SortImperfectCRLs); - return SECSuccess; - } - /* all CRLs are good, sort them by thisUpdate */ - qsort(cache->crls, cache->ncrls, sizeof(CachedCrl*), - SortCRLsByThisUpdate); - - if (cache->ncrls) - { - /* pick the newest CRL */ - selected = cache->crls[cache->ncrls-1]; - - /* and populate the cache */ - if (SECSuccess != CachedCrl_Populate(selected)) - { - return SECFailure; - } - } - - cache->selected = selected; - - return SECSuccess; -} - -/* initialize a DPCache object */ -static SECStatus DPCache_Create(CRLDPCache** returned, CERTCertificate* issuer, - const SECItem* subject, SECItem* dp) -{ - CRLDPCache* cache = NULL; - PORT_Assert(returned); - /* issuer and dp are allowed to be NULL */ - if (!returned || !subject) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - *returned = NULL; - cache = PORT_ZAlloc(sizeof(CRLDPCache)); - if (!cache) - { - return SECFailure; - } -#ifdef DPC_RWLOCK - cache->lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL); -#else - cache->lock = PR_NewLock(); -#endif - if (!cache->lock) - { - PORT_Free(cache); - return SECFailure; - } - if (issuer) - { - cache->issuer = CERT_DupCertificate(issuer); - } - cache->distributionPoint = SECITEM_DupItem(dp); - cache->subject = SECITEM_DupItem(subject); - cache->lastfetch = 0; - cache->lastcheck = 0; - *returned = cache; - return SECSuccess; -} - -/* create an issuer cache object (per CA subject ) */ -static SECStatus IssuerCache_Create(CRLIssuerCache** returned, - CERTCertificate* issuer, - const SECItem* subject, const SECItem* dp) -{ - SECStatus rv = SECSuccess; - CRLIssuerCache* cache = NULL; - PORT_Assert(returned); - PORT_Assert(subject); - /* issuer and dp are allowed to be NULL */ - if (!returned || !subject) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - *returned = NULL; - cache = (CRLIssuerCache*) PORT_ZAlloc(sizeof(CRLIssuerCache)); - if (!cache) - { - return SECFailure; - } - cache->subject = SECITEM_DupItem(subject); -#ifdef XCRL - cache->lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL); - if (!cache->lock) - { - rv = SECFailure; - } - if (SECSuccess == rv && issuer) - { - cache->issuer = CERT_DupCertificate(issuer); - if (!cache->issuer) - { - rv = SECFailure; - } - } -#endif - if (SECSuccess != rv) - { - PORT_Assert(SECSuccess == IssuerCache_Destroy(cache)); - return SECFailure; - } - *returned = cache; - return SECSuccess; -} - -/* add a DPCache to the issuer cache */ -static SECStatus IssuerCache_AddDP(CRLIssuerCache* cache, - CERTCertificate* issuer, - const SECItem* subject, - const SECItem* dp, - CRLDPCache** newdpc) -{ - /* now create the required DP cache object */ - if (!cache || !subject || !newdpc) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - if (!dp) - { - /* default distribution point */ - SECStatus rv = DPCache_Create(&cache->dpp, issuer, subject, NULL); - if (SECSuccess == rv) - { - *newdpc = cache->dpp; - return SECSuccess; - } - } - else - { - /* we should never hit this until we support multiple DPs */ - PORT_Assert(dp); - /* XCRL allocate a new distribution point cache object, initialize it, - and add it to the hash table of DPs */ - } - return SECFailure; -} - -/* add an IssuerCache to the global hash table of issuers */ -static SECStatus CRLCache_AddIssuer(CRLIssuerCache* issuer) -{ - PORT_Assert(issuer); - PORT_Assert(crlcache.issuers); - if (!issuer || !crlcache.issuers) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - if (NULL == PL_HashTableAdd(crlcache.issuers, (void*) issuer->subject, - (void*) issuer)) - { - return SECFailure; - } - return SECSuccess; -} - -/* retrieve the issuer cache object for a given issuer subject */ -static SECStatus CRLCache_GetIssuerCache(CRLCache* cache, - const SECItem* subject, - CRLIssuerCache** returned) -{ - /* we need to look up the issuer in the hash table */ - SECStatus rv = SECSuccess; - PORT_Assert(cache); - PORT_Assert(subject); - PORT_Assert(returned); - PORT_Assert(crlcache.issuers); - if (!cache || !subject || !returned || !crlcache.issuers) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - rv = SECFailure; - } - - if (SECSuccess == rv) - { - *returned = (CRLIssuerCache*) PL_HashTableLookup(crlcache.issuers, - (void*) subject); - } - - return rv; -} - -/* retrieve the full CRL object that best matches the content of a DPCache */ -static CERTSignedCrl* GetBestCRL(CRLDPCache* cache, PRBool entries) -{ - CachedCrl* acrl = NULL; - - PORT_Assert(cache); - if (!cache) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return NULL; - } - - if (0 == cache->ncrls) - { - /* empty cache*/ - PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); - return NULL; - } - - /* if we have a valid full CRL selected, return it */ - if (cache->selected) - { - return SEC_DupCrl(cache->selected->crl); - } - - /* otherwise, use latest valid DER CRL */ - acrl = cache->crls[cache->ncrls-1]; - - if (acrl && (PR_FALSE == GetOpaqueCRLFields(acrl->crl)->decodingError) ) - { - SECStatus rv = SECSuccess; - if (PR_TRUE == entries) - { - rv = CERT_CompleteCRLDecodeEntries(acrl->crl); - } - if (SECSuccess == rv) - { - return SEC_DupCrl(acrl->crl); - } - } - - PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); - return NULL; -} - -/* get a particular DPCache object from an IssuerCache */ -static CRLDPCache* IssuerCache_GetDPCache(CRLIssuerCache* cache, const SECItem* dp) -{ - CRLDPCache* dpp = NULL; - PORT_Assert(cache); - /* XCRL for now we only support the "default" DP, ie. the - full CRL. So we can return the global one without locking. In - the future we will have a lock */ - PORT_Assert(NULL == dp); - if (!cache || dp) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return NULL; - } -#ifdef XCRL - NSSRWLock_LockRead(cache->lock); -#endif - dpp = cache->dpp; -#ifdef XCRL - NSSRWLock_UnlockRead(cache->lock); -#endif - return dpp; -} - -/* get a DPCache object for the given issuer subject and dp - Automatically creates the cache object if it doesn't exist yet. - */ -SECStatus AcquireDPCache(CERTCertificate* issuer, const SECItem* subject, - const SECItem* dp, PRTime t, void* wincx, - CRLDPCache** dpcache, PRBool* writeLocked) -{ - SECStatus rv = SECSuccess; - CRLIssuerCache* issuercache = NULL; -#ifdef GLOBAL_RWLOCK - PRBool globalwrite = PR_FALSE; -#endif - PORT_Assert(crlcache.lock); - if (!crlcache.lock) - { - /* CRL cache is not initialized */ - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } -#ifdef GLOBAL_RWLOCK - NSSRWLock_LockRead(crlcache.lock); -#else - PR_Lock(crlcache.lock); -#endif - rv = CRLCache_GetIssuerCache(&crlcache, subject, &issuercache); - if (SECSuccess != rv) - { -#ifdef GLOBAL_RWLOCK - NSSRWLock_UnlockRead(crlcache.lock); -#else - PR_Unlock(crlcache.lock); -#endif - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - if (!issuercache) - { - /* there is no cache for this issuer yet. This means this is the - first time we look up a cert from that issuer, and we need to - create the cache. */ - - rv = IssuerCache_Create(&issuercache, issuer, subject, dp); - if (SECSuccess == rv && !issuercache) - { - PORT_Assert(issuercache); - rv = SECFailure; - } - - if (SECSuccess == rv) - { - /* This is the first time we look up a cert of this issuer. - Create the DPCache for this DP . */ - rv = IssuerCache_AddDP(issuercache, issuer, subject, dp, dpcache); - } - - if (SECSuccess == rv) - { - /* lock the DPCache for write to ensure the update happens in this - thread */ - *writeLocked = PR_TRUE; -#ifdef DPC_RWLOCK - NSSRWLock_LockWrite((*dpcache)->lock); -#else - PR_Lock((*dpcache)->lock); -#endif - } - - if (SECSuccess == rv) - { - /* now add the new issuer cache to the global hash table of - issuers */ -#ifdef GLOBAL_RWLOCK - CRLIssuerCache* existing = NULL; - NSSRWLock_UnlockRead(crlcache.lock); - /* when using a r/w lock for the global cache, check if the issuer - already exists before adding to the hash table */ - NSSRWLock_LockWrite(crlcache.lock); - globalwrite = PR_TRUE; - rv = CRLCache_GetIssuerCache(&crlcache, subject, &existing); - if (!existing) - { -#endif - rv = CRLCache_AddIssuer(issuercache); - if (SECSuccess != rv) - { - /* failure */ - rv = SECFailure; - } -#ifdef GLOBAL_RWLOCK - } - else - { - /* somebody else updated before we did */ - IssuerCache_Destroy(issuercache); /* destroy the new object */ - issuercache = existing; /* use the existing one */ - *dpcache = IssuerCache_GetDPCache(issuercache, dp); - } -#endif - } - - /* now unlock the global cache. We only want to lock the issuer hash - table addition. Holding it longer would hurt scalability */ -#ifdef GLOBAL_RWLOCK - if (PR_TRUE == globalwrite) - { - NSSRWLock_UnlockWrite(crlcache.lock); - globalwrite = PR_FALSE; - } - else - { - NSSRWLock_UnlockRead(crlcache.lock); - } -#else - PR_Unlock(crlcache.lock); -#endif - - /* if there was a failure adding an issuer cache object, destroy it */ - if (SECSuccess != rv && issuercache) - { - if (PR_TRUE == *writeLocked) - { -#ifdef DPC_RWLOCK - NSSRWLock_UnlockWrite((*dpcache)->lock); -#else - PR_Unlock((*dpcache)->lock); -#endif - } - IssuerCache_Destroy(issuercache); - issuercache = NULL; - } - - if (SECSuccess != rv) - { - return SECFailure; - } - } else - { -#ifdef GLOBAL_RWLOCK - NSSRWLock_UnlockRead(crlcache.lock); -#else - PR_Unlock(crlcache.lock); -#endif - *dpcache = IssuerCache_GetDPCache(issuercache, dp); - } - /* we now have a DPCache that we can use for lookups */ - /* lock it for read, unless we already locked for write */ - if (PR_FALSE == *writeLocked) - { -#ifdef DPC_RWLOCK - NSSRWLock_LockRead((*dpcache)->lock); -#else - PR_Lock((*dpcache)->lock); -#endif - } - - if (SECSuccess == rv) - { - /* currently there is always one and only one DPCache per issuer */ - PORT_Assert(*dpcache); - if (*dpcache) - { - /* make sure the DP cache is up to date before using it */ - rv = DPCache_GetUpToDate(*dpcache, issuer, PR_FALSE == *writeLocked, - t, wincx); - } - else - { - rv = SECFailure; - } - } - return rv; -} - -/* unlock access to the DPCache */ -void ReleaseDPCache(CRLDPCache* dpcache, PRBool writeLocked) -{ - if (!dpcache) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return; - } -#ifdef DPC_RWLOCK - if (PR_TRUE == writeLocked) - { - NSSRWLock_UnlockWrite(dpcache->lock); - } - else - { - NSSRWLock_UnlockRead(dpcache->lock); - } -#else - PR_Unlock(dpcache->lock); -#endif -} - -SECStatus -cert_CheckCertRevocationStatus(CERTCertificate* cert, CERTCertificate* issuer, - const SECItem* dp, PRTime t, void *wincx, - CERTRevocationStatus *revStatus, - CERTCRLEntryReasonCode *revReason) -{ - PRBool lockedwrite = PR_FALSE; - SECStatus rv = SECSuccess; - CRLDPCache* dpcache = NULL; - CERTRevocationStatus status = certRevocationStatusRevoked; - CERTCRLEntryReasonCode reason = crlEntryReasonUnspecified; - CERTCrlEntry* entry = NULL; - dpcacheStatus ds; - - if (!cert || !issuer) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - - if (revStatus) - { - *revStatus = status; - } - if (revReason) - { - *revReason = reason; - } - - if (t && SECSuccess != CERT_CheckCertValidTimes(issuer, t, PR_FALSE)) - { - /* we won't be able to check the CRL's signature if the issuer cert - is expired as of the time we are verifying. This may cause a valid - CRL to be cached as bad. short-circuit to avoid this case. */ - PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE); - return SECFailure; - } - - rv = AcquireDPCache(issuer, &issuer->derSubject, dp, t, wincx, &dpcache, - &lockedwrite); - PORT_Assert(SECSuccess == rv); - if (SECSuccess != rv) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - /* now look up the certificate SN in the DP cache's CRL */ - ds = DPCache_Lookup(dpcache, &cert->serialNumber, &entry); - switch (ds) - { - case dpcacheFoundEntry: - PORT_Assert(entry); - /* check the time if we have one */ - if (entry->revocationDate.data && entry->revocationDate.len) - { - PRTime revocationDate = 0; - if (SECSuccess == DER_DecodeTimeChoice(&revocationDate, - &entry->revocationDate)) - { - /* we got a good revocation date, only consider the - certificate revoked if the time we are inquiring about - is past the revocation date */ - if (t>=revocationDate) - { - rv = SECFailure; - } - else - { - status = certRevocationStatusValid; - } - } - else - { - /* invalid revocation date, consider the certificate - permanently revoked */ - rv = SECFailure; - } - } - else - { - /* no revocation date, certificate is permanently revoked */ - rv = SECFailure; - } - if (SECFailure == rv) - { - SECStatus rv2 = CERT_FindCRLEntryReasonExten(entry, &reason); - PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); - } - break; - - case dpcacheEmpty: - /* useful for NIST policy */ - status = certRevocationStatusUnknown; - break; - - case dpcacheNoEntry: - status = certRevocationStatusValid; - break; - - case dpcacheInvalidCacheError: - /* treat it as unknown and let the caller decide based on - the policy */ - status = certRevocationStatusUnknown; - break; - - default: - /* leave status as revoked */ - break; - } - - ReleaseDPCache(dpcache, lockedwrite); - if (revStatus) - { - *revStatus = status; - } - if (revReason) - { - *revReason = reason; - } - return rv; -} - -/* check CRL revocation status of given certificate and issuer */ -SECStatus -CERT_CheckCRL(CERTCertificate* cert, CERTCertificate* issuer, - const SECItem* dp, PRTime t, void* wincx) -{ - return cert_CheckCertRevocationStatus(cert, issuer, dp, t, wincx, - NULL, NULL); -} - -/* retrieve full CRL object that best matches the cache status */ -CERTSignedCrl * -SEC_FindCrlByName(CERTCertDBHandle *handle, SECItem *crlKey, int type) -{ - CERTSignedCrl* acrl = NULL; - CRLDPCache* dpcache = NULL; - SECStatus rv = SECSuccess; - PRBool writeLocked = PR_FALSE; - - if (!crlKey) - { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - - rv = AcquireDPCache(NULL, crlKey, NULL, 0, NULL, &dpcache, &writeLocked); - if (SECSuccess == rv) - { - acrl = GetBestCRL(dpcache, PR_TRUE); /* decode entries, because - SEC_FindCrlByName always returned fully decoded CRLs in the past */ - ReleaseDPCache(dpcache, writeLocked); - } - return acrl; -} - -/* invalidate the CRL cache for a given issuer, which forces a refetch of - CRL objects from PKCS#11 tokens */ -void CERT_CRLCacheRefreshIssuer(CERTCertDBHandle* dbhandle, SECItem* crlKey) -{ - CRLDPCache* cache = NULL; - SECStatus rv = SECSuccess; - PRBool writeLocked = PR_FALSE; - PRBool readlocked; - - (void) dbhandle; /* silence compiler warnings */ - - /* XCRL we will need to refresh all the DPs of the issuer in the future, - not just the default one */ - rv = AcquireDPCache(NULL, crlKey, NULL, 0, NULL, &cache, &writeLocked); - if (SECSuccess != rv) - { - return; - } - /* we need to invalidate the DPCache here */ - readlocked = (writeLocked == PR_TRUE? PR_FALSE : PR_TRUE); - DPCache_LockWrite(); - cache->refresh = PR_TRUE; - DPCache_UnlockWrite(); - ReleaseDPCache(cache, writeLocked); - return; -} - -/* add the specified RAM CRL object to the cache */ -SECStatus CERT_CacheCRL(CERTCertDBHandle* dbhandle, SECItem* newdercrl) -{ - CRLDPCache* cache = NULL; - SECStatus rv = SECSuccess; - PRBool writeLocked = PR_FALSE; - PRBool readlocked; - CachedCrl* returned = NULL; - PRBool added = PR_FALSE; - CERTSignedCrl* newcrl = NULL; - int realerror = 0; - - if (!dbhandle || !newdercrl) - { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - /* first decode the DER CRL to make sure it's OK */ - newcrl = CERT_DecodeDERCrlWithFlags(NULL, newdercrl, SEC_CRL_TYPE, - CRL_DECODE_DONT_COPY_DER | - CRL_DECODE_SKIP_ENTRIES); - - if (!newcrl) - { - return SECFailure; - } - - /* XXX check if it has IDP extension. If so, do not proceed and set error */ - - rv = AcquireDPCache(NULL, - &newcrl->crl.derName, - NULL, 0, NULL, &cache, &writeLocked); - if (SECSuccess == rv) - { - readlocked = (writeLocked == PR_TRUE? PR_FALSE : PR_TRUE); - - rv = CachedCrl_Create(&returned, newcrl, CRL_OriginExplicit); - if (SECSuccess == rv && returned) - { - DPCache_LockWrite(); - rv = DPCache_AddCRL(cache, returned, &added); - if (PR_TRUE != added) - { - realerror = PORT_GetError(); - CachedCrl_Destroy(returned); - returned = NULL; - } - DPCache_UnlockWrite(); - } - - ReleaseDPCache(cache, writeLocked); - - if (!added) - { - rv = SECFailure; - } - } - SEC_DestroyCrl(newcrl); /* free the CRL. Either it got added to the cache - and the refcount got bumped, or not, and thus we need to free its - RAM */ - if (realerror) - { - PORT_SetError(realerror); - } - return rv; -} - -/* remove the specified RAM CRL object from the cache */ -SECStatus CERT_UncacheCRL(CERTCertDBHandle* dbhandle, SECItem* olddercrl) -{ - CRLDPCache* cache = NULL; - SECStatus rv = SECSuccess; - PRBool writeLocked = PR_FALSE; - PRBool readlocked; - PRBool removed = PR_FALSE; - PRUint32 i; - CERTSignedCrl* oldcrl = NULL; - - if (!dbhandle || !olddercrl) - { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - /* first decode the DER CRL to make sure it's OK */ - oldcrl = CERT_DecodeDERCrlWithFlags(NULL, olddercrl, SEC_CRL_TYPE, - CRL_DECODE_DONT_COPY_DER | - CRL_DECODE_SKIP_ENTRIES); - - if (!oldcrl) - { - /* if this DER CRL can't decode, it can't be in the cache */ - return SECFailure; - } - - rv = AcquireDPCache(NULL, - &oldcrl->crl.derName, - NULL, 0, NULL, &cache, &writeLocked); - if (SECSuccess == rv) - { - CachedCrl* returned = NULL; - - readlocked = (writeLocked == PR_TRUE? PR_FALSE : PR_TRUE); - - rv = CachedCrl_Create(&returned, oldcrl, CRL_OriginExplicit); - if (SECSuccess == rv && returned) - { - DPCache_LockWrite(); - for (i=0;i<cache->ncrls;i++) - { - PRBool dupe = PR_FALSE, updated = PR_FALSE; - rv = CachedCrl_Compare(returned, cache->crls[i], - &dupe, &updated); - if (SECSuccess != rv) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - break; - } - if (PR_TRUE == dupe) - { - rv = DPCache_RemoveCRL(cache, i); /* got a match */ - if (SECSuccess == rv) { - cache->mustchoose = PR_TRUE; - removed = PR_TRUE; - } - break; - } - } - - DPCache_UnlockWrite(); - - if (SECSuccess != CachedCrl_Destroy(returned) ) { - rv = SECFailure; - } - } - - ReleaseDPCache(cache, writeLocked); - } - if (SECSuccess != SEC_DestroyCrl(oldcrl) ) { - /* need to do this because object is refcounted */ - rv = SECFailure; - } - if (SECSuccess == rv && PR_TRUE != removed) - { - PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); - } - return rv; -} - -SECStatus cert_AcquireNamedCRLCache(NamedCRLCache** returned) -{ - PORT_Assert(returned); - if (!namedCRLCache.lock) - { - PORT_Assert(0); - return SECFailure; - } - PR_Lock(namedCRLCache.lock); - *returned = &namedCRLCache; - return SECSuccess; -} - -/* This must be called only while cache is acquired, and the entry is only - * valid until cache is released. - */ -SECStatus cert_FindCRLByGeneralName(NamedCRLCache* ncc, - const SECItem* canonicalizedName, - NamedCRLCacheEntry** retEntry) -{ - if (!ncc || !canonicalizedName || !retEntry) - { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - *retEntry = (NamedCRLCacheEntry*) PL_HashTableLookup(namedCRLCache.entries, - (void*) canonicalizedName); - return SECSuccess; -} - -SECStatus cert_ReleaseNamedCRLCache(NamedCRLCache* ncc) -{ - if (!ncc) - { - return SECFailure; - } - if (!ncc->lock) - { - PORT_Assert(0); - return SECFailure; - } - PR_Unlock(namedCRLCache.lock); - return SECSuccess; -} - -/* creates new named cache entry from CRL, and tries to add it to CRL cache */ -static SECStatus addCRLToCache(CERTCertDBHandle* dbhandle, SECItem* crl, - const SECItem* canonicalizedName, - NamedCRLCacheEntry** newEntry) -{ - SECStatus rv = SECSuccess; - NamedCRLCacheEntry* entry = NULL; - - /* create new named entry */ - if (SECSuccess != NamedCRLCacheEntry_Create(newEntry) || !*newEntry) - { - /* no need to keep unused CRL around */ - SECITEM_ZfreeItem(crl, PR_TRUE); - return SECFailure; - } - entry = *newEntry; - entry->crl = crl; /* named CRL cache owns DER */ - entry->lastAttemptTime = PR_Now(); - entry->canonicalizedName = SECITEM_DupItem(canonicalizedName); - if (!entry->canonicalizedName) - { - rv = NamedCRLCacheEntry_Destroy(entry); /* destroys CRL too */ - PORT_Assert(SECSuccess == rv); - return SECFailure; - } - /* now, attempt to insert CRL into CRL cache */ - if (SECSuccess == CERT_CacheCRL(dbhandle, entry->crl)) - { - entry->inCRLCache = PR_TRUE; - entry->successfulInsertionTime = entry->lastAttemptTime; - } - else - { - switch (PR_GetError()) - { - case SEC_ERROR_CRL_ALREADY_EXISTS: - entry->dupe = PR_TRUE; - break; - - case SEC_ERROR_BAD_DER: - entry->badDER = PR_TRUE; - break; - - /* all other reasons */ - default: - entry->unsupported = PR_TRUE; - break; - } - rv = SECFailure; - /* no need to keep unused CRL around */ - SECITEM_ZfreeItem(entry->crl, PR_TRUE); - entry->crl = NULL; - } - return rv; -} - -/* take ownership of CRL, and insert it into the named CRL cache - * and indexed CRL cache - */ -SECStatus cert_CacheCRLByGeneralName(CERTCertDBHandle* dbhandle, SECItem* crl, - const SECItem* canonicalizedName) -{ - NamedCRLCacheEntry* oldEntry, * newEntry = NULL; - NamedCRLCache* ncc = NULL; - SECStatus rv = SECSuccess, rv2; - - PORT_Assert(namedCRLCache.lock); - PORT_Assert(namedCRLCache.entries); - - if (!crl || !canonicalizedName) - { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - rv = cert_AcquireNamedCRLCache(&ncc); - PORT_Assert(SECSuccess == rv); - if (SECSuccess != rv) - { - SECITEM_ZfreeItem(crl, PR_TRUE); - return SECFailure; - } - rv = cert_FindCRLByGeneralName(ncc, canonicalizedName, &oldEntry); - PORT_Assert(SECSuccess == rv); - if (SECSuccess != rv) - { - rv = cert_ReleaseNamedCRLCache(ncc); - SECITEM_ZfreeItem(crl, PR_TRUE); - return SECFailure; - } - if (SECSuccess == addCRLToCache(dbhandle, crl, canonicalizedName, - &newEntry) ) - { - if (!oldEntry) - { - /* add new good entry to the hash table */ - if (NULL == PL_HashTableAdd(namedCRLCache.entries, - (void*) newEntry->canonicalizedName, - (void*) newEntry)) - { - PORT_Assert(0); - rv2 = NamedCRLCacheEntry_Destroy(newEntry); - PORT_Assert(SECSuccess == rv2); - rv = SECFailure; - } - } - else - { - PRBool removed; - /* remove the old CRL from the cache if needed */ - if (oldEntry->inCRLCache) - { - rv = CERT_UncacheCRL(dbhandle, oldEntry->crl); - PORT_Assert(SECSuccess == rv); - } - removed = PL_HashTableRemove(namedCRLCache.entries, - (void*) oldEntry->canonicalizedName); - PORT_Assert(removed); - if (!removed) - { - rv = SECFailure; - /* leak old entry since we couldn't remove it from the hash table */ - } - else - { - rv2 = NamedCRLCacheEntry_Destroy(oldEntry); - PORT_Assert(SECSuccess == rv2); - } - if (NULL == PL_HashTableAdd(namedCRLCache.entries, - (void*) newEntry->canonicalizedName, - (void*) newEntry)) - { - PORT_Assert(0); - rv = SECFailure; - } - } - } else - { - /* error adding new CRL to cache */ - if (!oldEntry) - { - /* no old cache entry, use the new one even though it's bad */ - if (NULL == PL_HashTableAdd(namedCRLCache.entries, - (void*) newEntry->canonicalizedName, - (void*) newEntry)) - { - PORT_Assert(0); - rv = SECFailure; - } - } - else - { - if (oldEntry->inCRLCache) - { - /* previous cache entry was good, keep it and update time */ - oldEntry-> lastAttemptTime = newEntry->lastAttemptTime; - /* throw away new bad entry */ - rv = NamedCRLCacheEntry_Destroy(newEntry); - PORT_Assert(SECSuccess == rv); - } - else - { - /* previous cache entry was bad, just replace it */ - PRBool removed = PL_HashTableRemove(namedCRLCache.entries, - (void*) oldEntry->canonicalizedName); - PORT_Assert(removed); - if (!removed) - { - /* leak old entry since we couldn't remove it from the hash table */ - rv = SECFailure; - } - else - { - rv2 = NamedCRLCacheEntry_Destroy(oldEntry); - PORT_Assert(SECSuccess == rv2); - } - if (NULL == PL_HashTableAdd(namedCRLCache.entries, - (void*) newEntry->canonicalizedName, - (void*) newEntry)) - { - PORT_Assert(0); - rv = SECFailure; - } - } - } - } - rv2 = cert_ReleaseNamedCRLCache(ncc); - PORT_Assert(SECSuccess == rv2); - - return rv; -} - -static SECStatus CachedCrl_Create(CachedCrl** returned, CERTSignedCrl* crl, - CRLOrigin origin) -{ - CachedCrl* newcrl = NULL; - if (!returned) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - newcrl = PORT_ZAlloc(sizeof(CachedCrl)); - if (!newcrl) - { - return SECFailure; - } - newcrl->crl = SEC_DupCrl(crl); - newcrl->origin = origin; - *returned = newcrl; - return SECSuccess; -} - -/* empty the cache content */ -static SECStatus CachedCrl_Depopulate(CachedCrl* crl) -{ - if (!crl) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - /* destroy the hash table */ - if (crl->entries) - { - PL_HashTableDestroy(crl->entries); - crl->entries = NULL; - } - - /* free the pre buffer */ - if (crl->prebuffer) - { - PreAllocator_Destroy(crl->prebuffer); - crl->prebuffer = NULL; - } - return SECSuccess; -} - -static SECStatus CachedCrl_Destroy(CachedCrl* crl) -{ - if (!crl) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - CachedCrl_Depopulate(crl); - SEC_DestroyCrl(crl->crl); - PORT_Free(crl); - return SECSuccess; -} - -/* create hash table of CRL entries */ -static SECStatus CachedCrl_Populate(CachedCrl* crlobject) -{ - SECStatus rv = SECFailure; - CERTCrlEntry** crlEntry = NULL; - PRUint32 numEntries = 0; - - if (!crlobject) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - /* complete the entry decoding . XXX thread-safety of CRL object */ - rv = CERT_CompleteCRLDecodeEntries(crlobject->crl); - if (SECSuccess != rv) - { - crlobject->unbuildable = PR_TRUE; /* don't try to build this again */ - return SECFailure; - } - - if (crlobject->entries && crlobject->prebuffer) - { - /* cache is already built */ - return SECSuccess; - } - - /* build the hash table from the full CRL */ - /* count CRL entries so we can pre-allocate space for hash table entries */ - for (crlEntry = crlobject->crl->crl.entries; crlEntry && *crlEntry; - crlEntry++) - { - numEntries++; - } - crlobject->prebuffer = PreAllocator_Create(numEntries*sizeof(PLHashEntry)); - PORT_Assert(crlobject->prebuffer); - if (!crlobject->prebuffer) - { - return SECFailure; - } - /* create a new hash table */ - crlobject->entries = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, - PL_CompareValues, &preAllocOps, crlobject->prebuffer); - PORT_Assert(crlobject->entries); - if (!crlobject->entries) - { - return SECFailure; - } - /* add all serial numbers to the hash table */ - for (crlEntry = crlobject->crl->crl.entries; crlEntry && *crlEntry; - crlEntry++) - { - PL_HashTableAdd(crlobject->entries, &(*crlEntry)->serialNumber, - *crlEntry); - } - - return SECSuccess; -} - -/* returns true if there are CRLs from PKCS#11 slots */ -static PRBool DPCache_HasTokenCRLs(CRLDPCache* cache) -{ - PRBool answer = PR_FALSE; - PRUint32 i; - for (i=0;i<cache->ncrls;i++) - { - if (cache->crls[i] && (CRL_OriginToken == cache->crls[i]->origin) ) - { - answer = PR_TRUE; - break; - } - } - return answer; -} - -/* are these CRLs the same, as far as the cache is concerned ? */ -/* are these CRLs the same token object but with different DER ? - This can happen if the DER CRL got updated in the token, but the PKCS#11 - object ID did not change. NSS softoken has the unfortunate property to - never change the object ID for CRL objects. */ -static SECStatus CachedCrl_Compare(CachedCrl* a, CachedCrl* b, PRBool* isDupe, - PRBool* isUpdated) -{ - PORT_Assert(a); - PORT_Assert(b); - PORT_Assert(isDupe); - PORT_Assert(isUpdated); - if (!a || !b || !isDupe || !isUpdated || !a->crl || !b->crl) - { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - - *isDupe = *isUpdated = PR_FALSE; - - if (a == b) - { - /* dupe */ - *isDupe = PR_TRUE; - *isUpdated = PR_FALSE; - return SECSuccess; - } - if (b->origin != a->origin) - { - /* CRLs of different origins are not considered dupes, - and can't be updated either */ - return SECSuccess; - } - if (CRL_OriginToken == b->origin) - { - /* for token CRLs, slot and PKCS#11 object handle must match for CRL - to truly be a dupe */ - if ( (b->crl->slot == a->crl->slot) && - (b->crl->pkcs11ID == a->crl->pkcs11ID) ) - { - /* ASN.1 DER needs to match for dupe check */ - /* could optimize by just checking a few fields like thisUpdate */ - if ( SECEqual == SECITEM_CompareItem(b->crl->derCrl, - a->crl->derCrl) ) - { - *isDupe = PR_TRUE; - } - else - { - *isUpdated = PR_TRUE; - } - } - return SECSuccess; - } - if (CRL_OriginExplicit == b->origin) - { - /* We need to make sure this is the same object that the user provided - to CERT_CacheCRL previously. That API takes a SECItem*, thus, we - just do a pointer comparison here. - */ - if (b->crl->derCrl == a->crl->derCrl) - { - *isDupe = PR_TRUE; - } - } - return SECSuccess; -} diff --git a/security/nss/lib/certdb/genname.c b/security/nss/lib/certdb/genname.c deleted file mode 100644 index cf63a56d7..000000000 --- a/security/nss/lib/certdb/genname.c +++ /dev/null @@ -1,1861 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.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 "plarena.h" -#include "seccomon.h" -#include "secitem.h" -#include "secoidt.h" -#include "secasn1.h" -#include "secder.h" -#include "certt.h" -#include "cert.h" -#include "certi.h" -#include "xconst.h" -#include "secerr.h" -#include "secoid.h" -#include "prprf.h" -#include "genname.h" - -SEC_ASN1_MKSUB(SEC_AnyTemplate) -SEC_ASN1_MKSUB(SEC_IntegerTemplate) -SEC_ASN1_MKSUB(SEC_IA5StringTemplate) -SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) -SEC_ASN1_MKSUB(SEC_OctetStringTemplate) - -static const SEC_ASN1Template CERTNameConstraintTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNameConstraint) }, - { SEC_ASN1_ANY, offsetof(CERTNameConstraint, DERName) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, - offsetof(CERTNameConstraint, min), - SEC_ASN1_SUB(SEC_IntegerTemplate) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, - offsetof(CERTNameConstraint, max), - SEC_ASN1_SUB(SEC_IntegerTemplate) }, - { 0, } -}; - -const SEC_ASN1Template CERT_NameConstraintSubtreeSubTemplate[] = { - { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, 0, SEC_ASN1_SUB(SEC_AnyTemplate) } -}; - -static const SEC_ASN1Template CERTNameConstraintsTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNameConstraints) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(CERTNameConstraints, DERPermited), - CERT_NameConstraintSubtreeSubTemplate}, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, - offsetof(CERTNameConstraints, DERExcluded), - CERT_NameConstraintSubtreeSubTemplate}, - { 0, } -}; - - -static const SEC_ASN1Template CERTOthNameTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(OtherName) }, - { SEC_ASN1_OBJECT_ID, - offsetof(OtherName, oid) }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | - SEC_ASN1_XTRN | 0, offsetof(OtherName, name), - SEC_ASN1_SUB(SEC_AnyTemplate) }, - { 0, } -}; - -static const SEC_ASN1Template CERTOtherNameTemplate[] = { - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0 , - offsetof(CERTGeneralName, name.OthName), CERTOthNameTemplate, - sizeof(CERTGeneralName) } -}; - -static const SEC_ASN1Template CERTOtherName2Template[] = { - { SEC_ASN1_SEQUENCE | SEC_ASN1_CONTEXT_SPECIFIC | 0 , - 0, NULL, sizeof(CERTGeneralName) }, - { SEC_ASN1_OBJECT_ID, - offsetof(CERTGeneralName, name.OthName) + offsetof(OtherName, oid) }, - { SEC_ASN1_ANY, - offsetof(CERTGeneralName, name.OthName) + offsetof(OtherName, name) }, - { 0, } -}; - -static const SEC_ASN1Template CERT_RFC822NameTemplate[] = { - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1 , - offsetof(CERTGeneralName, name.other), - SEC_ASN1_SUB(SEC_IA5StringTemplate), - sizeof (CERTGeneralName)} -}; - -static const SEC_ASN1Template CERT_DNSNameTemplate[] = { - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2 , - offsetof(CERTGeneralName, name.other), - SEC_ASN1_SUB(SEC_IA5StringTemplate), - sizeof (CERTGeneralName)} -}; - -static const SEC_ASN1Template CERT_X400AddressTemplate[] = { - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_XTRN | 3, - offsetof(CERTGeneralName, name.other), SEC_ASN1_SUB(SEC_AnyTemplate), - sizeof (CERTGeneralName)} -}; - -static const SEC_ASN1Template CERT_DirectoryNameTemplate[] = { - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | - SEC_ASN1_XTRN | 4, offsetof(CERTGeneralName, derDirectoryName), - SEC_ASN1_SUB(SEC_AnyTemplate), sizeof (CERTGeneralName)} -}; - - -static const SEC_ASN1Template CERT_EDIPartyNameTemplate[] = { - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_XTRN | 5, - offsetof(CERTGeneralName, name.other), SEC_ASN1_SUB(SEC_AnyTemplate), - sizeof (CERTGeneralName)} -}; - -static const SEC_ASN1Template CERT_URITemplate[] = { - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 6 , - offsetof(CERTGeneralName, name.other), - SEC_ASN1_SUB(SEC_IA5StringTemplate), - sizeof (CERTGeneralName)} -}; - -static const SEC_ASN1Template CERT_IPAddressTemplate[] = { - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 7 , - offsetof(CERTGeneralName, name.other), - SEC_ASN1_SUB(SEC_OctetStringTemplate), - sizeof (CERTGeneralName)} -}; - -static const SEC_ASN1Template CERT_RegisteredIDTemplate[] = { - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 8 , - offsetof(CERTGeneralName, name.other), - SEC_ASN1_SUB(SEC_ObjectIDTemplate), - sizeof (CERTGeneralName)} -}; - - -const SEC_ASN1Template CERT_GeneralNamesTemplate[] = { - { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN , 0, SEC_ASN1_SUB(SEC_AnyTemplate) } -}; - - - -CERTGeneralName * -CERT_NewGeneralName(PLArenaPool *arena, CERTGeneralNameType type) -{ - CERTGeneralName *name = arena - ? PORT_ArenaZNew(arena, CERTGeneralName) - : PORT_ZNew(CERTGeneralName); - if (name) { - name->type = type; - name->l.prev = name->l.next = &name->l; - } - return name; -} - -/* Copy content of one General Name to another. -** Caller has allocated destination general name. -** This function does not change the destinate's GeneralName's list linkage. -*/ -SECStatus -cert_CopyOneGeneralName(PRArenaPool *arena, - CERTGeneralName *dest, - CERTGeneralName *src) -{ - SECStatus rv; - void *mark = NULL; - - PORT_Assert(dest != NULL); - dest->type = src->type; - - mark = PORT_ArenaMark(arena); - - switch (src->type) { - case certDirectoryName: - rv = SECITEM_CopyItem(arena, &dest->derDirectoryName, - &src->derDirectoryName); - if (rv == SECSuccess) - rv = CERT_CopyName(arena, &dest->name.directoryName, - &src->name.directoryName); - break; - - case certOtherName: - rv = SECITEM_CopyItem(arena, &dest->name.OthName.name, - &src->name.OthName.name); - if (rv == SECSuccess) - rv = SECITEM_CopyItem(arena, &dest->name.OthName.oid, - &src->name.OthName.oid); - break; - - default: - rv = SECITEM_CopyItem(arena, &dest->name.other, - &src->name.other); - break; - - } - if (rv != SECSuccess) { - PORT_ArenaRelease(arena, mark); - } else { - PORT_ArenaUnmark(arena, mark); - } - return rv; -} - - -void -CERT_DestroyGeneralNameList(CERTGeneralNameList *list) -{ - PZLock *lock; - - if (list != NULL) { - lock = list->lock; - PZ_Lock(lock); - if (--list->refCount <= 0 && list->arena != NULL) { - PORT_FreeArena(list->arena, PR_FALSE); - PZ_Unlock(lock); - PZ_DestroyLock(lock); - } else { - PZ_Unlock(lock); - } - } - return; -} - -CERTGeneralNameList * -CERT_CreateGeneralNameList(CERTGeneralName *name) { - PRArenaPool *arena; - CERTGeneralNameList *list = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) { - goto done; - } - list = PORT_ArenaZNew(arena, CERTGeneralNameList); - if (!list) - goto loser; - if (name != NULL) { - SECStatus rv; - list->name = CERT_NewGeneralName(arena, (CERTGeneralNameType)0); - if (!list->name) - goto loser; - rv = CERT_CopyGeneralName(arena, list->name, name); - if (rv != SECSuccess) - goto loser; - } - list->lock = PZ_NewLock(nssILockList); - if (!list->lock) - goto loser; - list->arena = arena; - list->refCount = 1; -done: - return list; - -loser: - PORT_FreeArena(arena, PR_FALSE); - return NULL; -} - -CERTGeneralName * -CERT_GetNextGeneralName(CERTGeneralName *current) -{ - PRCList *next; - - next = current->l.next; - return (CERTGeneralName *) (((char *) next) - offsetof(CERTGeneralName, l)); -} - -CERTGeneralName * -CERT_GetPrevGeneralName(CERTGeneralName *current) -{ - PRCList *prev; - prev = current->l.prev; - return (CERTGeneralName *) (((char *) prev) - offsetof(CERTGeneralName, l)); -} - -CERTNameConstraint * -CERT_GetNextNameConstraint(CERTNameConstraint *current) -{ - PRCList *next; - - next = current->l.next; - return (CERTNameConstraint *) (((char *) next) - offsetof(CERTNameConstraint, l)); -} - -CERTNameConstraint * -CERT_GetPrevNameConstraint(CERTNameConstraint *current) -{ - PRCList *prev; - prev = current->l.prev; - return (CERTNameConstraint *) (((char *) prev) - offsetof(CERTNameConstraint, l)); -} - -SECItem * -CERT_EncodeGeneralName(CERTGeneralName *genName, SECItem *dest, PRArenaPool *arena) -{ - - const SEC_ASN1Template * template; - - PORT_Assert(arena); - if (arena == NULL) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - /* TODO: mark arena */ - if (dest == NULL) { - dest = PORT_ArenaZNew(arena, SECItem); - if (!dest) - goto loser; - } - if (genName->type == certDirectoryName) { - if (genName->derDirectoryName.data == NULL) { - /* The field hasn't been encoded yet. */ - SECItem * pre_dest = - SEC_ASN1EncodeItem (arena, &(genName->derDirectoryName), - &(genName->name.directoryName), - CERT_NameTemplate); - if (!pre_dest) - goto loser; - } - if (genName->derDirectoryName.data == NULL) { - goto loser; - } - } - switch (genName->type) { - case certURI: template = CERT_URITemplate; break; - case certRFC822Name: template = CERT_RFC822NameTemplate; break; - case certDNSName: template = CERT_DNSNameTemplate; break; - case certIPAddress: template = CERT_IPAddressTemplate; break; - case certOtherName: template = CERTOtherNameTemplate; break; - case certRegisterID: template = CERT_RegisteredIDTemplate; break; - /* for this type, we expect the value is already encoded */ - case certEDIPartyName: template = CERT_EDIPartyNameTemplate; break; - /* for this type, we expect the value is already encoded */ - case certX400Address: template = CERT_X400AddressTemplate; break; - case certDirectoryName: template = CERT_DirectoryNameTemplate; break; - default: - PORT_Assert(0); goto loser; - } - dest = SEC_ASN1EncodeItem(arena, dest, genName, template); - if (!dest) { - goto loser; - } - /* TODO: unmark arena */ - return dest; -loser: - /* TODO: release arena back to mark */ - return NULL; -} - -SECItem ** -cert_EncodeGeneralNames(PRArenaPool *arena, CERTGeneralName *names) -{ - CERTGeneralName *current_name; - SECItem **items = NULL; - int count = 0; - int i; - PRCList *head; - - PORT_Assert(arena); - /* TODO: mark arena */ - current_name = names; - if (names != NULL) { - count = 1; - } - head = &(names->l); - while (current_name->l.next != head) { - current_name = CERT_GetNextGeneralName(current_name); - ++count; - } - current_name = CERT_GetNextGeneralName(current_name); - items = PORT_ArenaNewArray(arena, SECItem *, count + 1); - if (items == NULL) { - goto loser; - } - for (i = 0; i < count; i++) { - items[i] = CERT_EncodeGeneralName(current_name, (SECItem *)NULL, arena); - if (items[i] == NULL) { - goto loser; - } - current_name = CERT_GetNextGeneralName(current_name); - } - items[i] = NULL; - /* TODO: unmark arena */ - return items; -loser: - /* TODO: release arena to mark */ - return NULL; -} - -CERTGeneralName * -CERT_DecodeGeneralName(PRArenaPool *reqArena, - SECItem *encodedName, - CERTGeneralName *genName) -{ - const SEC_ASN1Template * template; - CERTGeneralNameType genNameType; - SECStatus rv = SECSuccess; - SECItem* newEncodedName; - - if (!reqArena) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - /* make a copy for decoding so the data decoded with QuickDER doesn't - point to temporary memory */ - newEncodedName = SECITEM_ArenaDupItem(reqArena, encodedName); - if (!newEncodedName) { - return NULL; - } - /* TODO: mark arena */ - genNameType = (CERTGeneralNameType)((*(newEncodedName->data) & 0x0f) + 1); - if (genName == NULL) { - genName = CERT_NewGeneralName(reqArena, genNameType); - if (!genName) - goto loser; - } else { - genName->type = genNameType; - genName->l.prev = genName->l.next = &genName->l; - } - - switch (genNameType) { - case certURI: template = CERT_URITemplate; break; - case certRFC822Name: template = CERT_RFC822NameTemplate; break; - case certDNSName: template = CERT_DNSNameTemplate; break; - case certIPAddress: template = CERT_IPAddressTemplate; break; - case certOtherName: template = CERTOtherNameTemplate; break; - case certRegisterID: template = CERT_RegisteredIDTemplate; break; - case certEDIPartyName: template = CERT_EDIPartyNameTemplate; break; - case certX400Address: template = CERT_X400AddressTemplate; break; - case certDirectoryName: template = CERT_DirectoryNameTemplate; break; - default: - goto loser; - } - rv = SEC_QuickDERDecodeItem(reqArena, genName, template, newEncodedName); - if (rv != SECSuccess) - goto loser; - if (genNameType == certDirectoryName) { - rv = SEC_QuickDERDecodeItem(reqArena, &(genName->name.directoryName), - CERT_NameTemplate, - &(genName->derDirectoryName)); - if (rv != SECSuccess) - goto loser; - } - - /* TODO: unmark arena */ - return genName; -loser: - /* TODO: release arena to mark */ - return NULL; -} - -CERTGeneralName * -cert_DecodeGeneralNames (PRArenaPool *arena, - SECItem **encodedGenName) -{ - PRCList *head = NULL; - PRCList *tail = NULL; - CERTGeneralName *currentName = NULL; - - PORT_Assert(arena); - if (!encodedGenName || !arena) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - /* TODO: mark arena */ - while (*encodedGenName != NULL) { - currentName = CERT_DecodeGeneralName(arena, *encodedGenName, NULL); - if (currentName == NULL) - break; - if (head == NULL) { - head = &(currentName->l); - tail = head; - } - currentName->l.next = head; - currentName->l.prev = tail; - tail = head->prev = tail->next = &(currentName->l); - encodedGenName++; - } - if (currentName) { - /* TODO: unmark arena */ - return CERT_GetNextGeneralName(currentName); - } - /* TODO: release arena to mark */ - return NULL; -} - -void -CERT_DestroyGeneralName(CERTGeneralName *name) -{ - cert_DestroyGeneralNames(name); -} - -SECStatus -cert_DestroyGeneralNames(CERTGeneralName *name) -{ - CERTGeneralName *first; - CERTGeneralName *next = NULL; - - - first = name; - do { - next = CERT_GetNextGeneralName(name); - PORT_Free(name); - name = next; - } while (name != first); - return SECSuccess; -} - -static SECItem * -cert_EncodeNameConstraint(CERTNameConstraint *constraint, - SECItem *dest, - PRArenaPool *arena) -{ - PORT_Assert(arena); - if (dest == NULL) { - dest = PORT_ArenaZNew(arena, SECItem); - if (dest == NULL) { - return NULL; - } - } - CERT_EncodeGeneralName(&(constraint->name), &(constraint->DERName), arena); - - dest = SEC_ASN1EncodeItem (arena, dest, constraint, - CERTNameConstraintTemplate); - return dest; -} - -SECStatus -cert_EncodeNameConstraintSubTree(CERTNameConstraint *constraints, - PRArenaPool *arena, - SECItem ***dest, - PRBool permited) -{ - CERTNameConstraint *current_constraint = constraints; - SECItem **items = NULL; - int count = 0; - int i; - PRCList *head; - - PORT_Assert(arena); - /* TODO: mark arena */ - if (constraints != NULL) { - count = 1; - } - head = &constraints->l; - while (current_constraint->l.next != head) { - current_constraint = CERT_GetNextNameConstraint(current_constraint); - ++count; - } - current_constraint = CERT_GetNextNameConstraint(current_constraint); - items = PORT_ArenaZNewArray(arena, SECItem *, count + 1); - if (items == NULL) { - goto loser; - } - for (i = 0; i < count; i++) { - items[i] = cert_EncodeNameConstraint(current_constraint, - (SECItem *) NULL, arena); - if (items[i] == NULL) { - goto loser; - } - current_constraint = CERT_GetNextNameConstraint(current_constraint); - } - *dest = items; - if (*dest == NULL) { - goto loser; - } - /* TODO: unmark arena */ - return SECSuccess; -loser: - /* TODO: release arena to mark */ - return SECFailure; -} - -SECStatus -cert_EncodeNameConstraints(CERTNameConstraints *constraints, - PRArenaPool *arena, - SECItem *dest) -{ - SECStatus rv = SECSuccess; - - PORT_Assert(arena); - /* TODO: mark arena */ - if (constraints->permited != NULL) { - rv = cert_EncodeNameConstraintSubTree(constraints->permited, arena, - &constraints->DERPermited, - PR_TRUE); - if (rv == SECFailure) { - goto loser; - } - } - if (constraints->excluded != NULL) { - rv = cert_EncodeNameConstraintSubTree(constraints->excluded, arena, - &constraints->DERExcluded, - PR_FALSE); - if (rv == SECFailure) { - goto loser; - } - } - dest = SEC_ASN1EncodeItem(arena, dest, constraints, - CERTNameConstraintsTemplate); - if (dest == NULL) { - goto loser; - } - /* TODO: unmark arena */ - return SECSuccess; -loser: - /* TODO: release arena to mark */ - return SECFailure; -} - - -CERTNameConstraint * -cert_DecodeNameConstraint(PRArenaPool *reqArena, - SECItem *encodedConstraint) -{ - CERTNameConstraint *constraint; - SECStatus rv = SECSuccess; - CERTGeneralName *temp; - SECItem* newEncodedConstraint; - - if (!reqArena) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - newEncodedConstraint = SECITEM_ArenaDupItem(reqArena, encodedConstraint); - if (!newEncodedConstraint) { - return NULL; - } - /* TODO: mark arena */ - constraint = PORT_ArenaZNew(reqArena, CERTNameConstraint); - if (!constraint) - goto loser; - rv = SEC_QuickDERDecodeItem(reqArena, constraint, - CERTNameConstraintTemplate, - newEncodedConstraint); - if (rv != SECSuccess) { - goto loser; - } - temp = CERT_DecodeGeneralName(reqArena, &(constraint->DERName), - &(constraint->name)); - if (temp != &(constraint->name)) { - goto loser; - } - - /* ### sjlee: since the name constraint contains only one - * CERTGeneralName, the list within CERTGeneralName shouldn't - * point anywhere else. Otherwise, bad things will happen. - */ - constraint->name.l.prev = constraint->name.l.next = &(constraint->name.l); - /* TODO: unmark arena */ - return constraint; -loser: - /* TODO: release arena back to mark */ - return NULL; -} - -CERTNameConstraint * -cert_DecodeNameConstraintSubTree(PRArenaPool *arena, - SECItem **subTree, - PRBool permited) -{ - CERTNameConstraint *current = NULL; - CERTNameConstraint *first = NULL; - CERTNameConstraint *last = NULL; - int i = 0; - - PORT_Assert(arena); - /* TODO: mark arena */ - while (subTree[i] != NULL) { - current = cert_DecodeNameConstraint(arena, subTree[i]); - if (current == NULL) { - goto loser; - } - if (last == NULL) { - first = last = current; - } - current->l.prev = &(last->l); - current->l.next = last->l.next; - last->l.next = &(current->l); - i++; - } - first->l.prev = &(current->l); - /* TODO: unmark arena */ - return first; -loser: - /* TODO: release arena back to mark */ - return NULL; -} - -CERTNameConstraints * -cert_DecodeNameConstraints(PRArenaPool *reqArena, - SECItem *encodedConstraints) -{ - CERTNameConstraints *constraints; - SECStatus rv; - SECItem* newEncodedConstraints; - - if (!reqArena) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - PORT_Assert(encodedConstraints); - newEncodedConstraints = SECITEM_ArenaDupItem(reqArena, encodedConstraints); - - /* TODO: mark arena */ - constraints = PORT_ArenaZNew(reqArena, CERTNameConstraints); - if (constraints == NULL) { - goto loser; - } - rv = SEC_QuickDERDecodeItem(reqArena, constraints, - CERTNameConstraintsTemplate, - newEncodedConstraints); - if (rv != SECSuccess) { - goto loser; - } - if (constraints->DERPermited != NULL && - constraints->DERPermited[0] != NULL) { - constraints->permited = - cert_DecodeNameConstraintSubTree(reqArena, - constraints->DERPermited, - PR_TRUE); - if (constraints->permited == NULL) { - goto loser; - } - } - if (constraints->DERExcluded != NULL && - constraints->DERExcluded[0] != NULL) { - constraints->excluded = - cert_DecodeNameConstraintSubTree(reqArena, - constraints->DERExcluded, - PR_FALSE); - if (constraints->excluded == NULL) { - goto loser; - } - } - /* TODO: unmark arena */ - return constraints; -loser: - /* TODO: release arena back to mark */ - return NULL; -} - -/* Copy a chain of one or more general names to a destination chain. -** Caller has allocated at least the first destination GeneralName struct. -** Both source and destination chains are circular doubly-linked lists. -** The first source struct is copied to the first destination struct. -** If the source chain has more than one member, and the destination chain -** has only one member, then this function allocates new structs for all but -** the first copy from the arena and links them into the destination list. -** If the destination struct is part of a list with more than one member, -** then this function traverses both the source and destination lists, -** copying each source struct to the corresponding dest struct. -** In that case, the destination list MUST contain at least as many -** structs as the source list or some dest entries will be overwritten. -*/ -SECStatus -CERT_CopyGeneralName(PRArenaPool *arena, - CERTGeneralName *dest, - CERTGeneralName *src) -{ - SECStatus rv; - CERTGeneralName *destHead = dest; - CERTGeneralName *srcHead = src; - - PORT_Assert(dest != NULL); - if (!dest) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - /* TODO: mark arena */ - do { - rv = cert_CopyOneGeneralName(arena, dest, src); - if (rv != SECSuccess) - goto loser; - src = CERT_GetNextGeneralName(src); - /* if there is only one general name, we shouldn't do this */ - if (src != srcHead) { - if (dest->l.next == &destHead->l) { - CERTGeneralName *temp; - temp = CERT_NewGeneralName(arena, (CERTGeneralNameType)0); - if (!temp) - goto loser; - temp->l.next = &destHead->l; - temp->l.prev = &dest->l; - destHead->l.prev = &temp->l; - dest->l.next = &temp->l; - dest = temp; - } else { - dest = CERT_GetNextGeneralName(dest); - } - } - } while (src != srcHead && rv == SECSuccess); - /* TODO: unmark arena */ - return rv; -loser: - /* TODO: release back to mark */ - return SECFailure; -} - - -CERTGeneralNameList * -CERT_DupGeneralNameList(CERTGeneralNameList *list) -{ - if (list != NULL) { - PZ_Lock(list->lock); - list->refCount++; - PZ_Unlock(list->lock); - } - return list; -} - -/* Allocate space and copy CERTNameConstraint from src to dest */ -CERTNameConstraint * -CERT_CopyNameConstraint(PRArenaPool *arena, - CERTNameConstraint *dest, - CERTNameConstraint *src) -{ - SECStatus rv; - - /* TODO: mark arena */ - if (dest == NULL) { - dest = PORT_ArenaZNew(arena, CERTNameConstraint); - if (!dest) - goto loser; - /* mark that it is not linked */ - dest->name.l.prev = dest->name.l.next = &(dest->name.l); - } - rv = CERT_CopyGeneralName(arena, &dest->name, &src->name); - if (rv != SECSuccess) { - goto loser; - } - rv = SECITEM_CopyItem(arena, &dest->DERName, &src->DERName); - if (rv != SECSuccess) { - goto loser; - } - rv = SECITEM_CopyItem(arena, &dest->min, &src->min); - if (rv != SECSuccess) { - goto loser; - } - rv = SECITEM_CopyItem(arena, &dest->max, &src->max); - if (rv != SECSuccess) { - goto loser; - } - dest->l.prev = dest->l.next = &dest->l; - /* TODO: unmark arena */ - return dest; -loser: - /* TODO: release arena to mark */ - return NULL; -} - - -CERTGeneralName * -cert_CombineNamesLists(CERTGeneralName *list1, CERTGeneralName *list2) -{ - PRCList *begin1; - PRCList *begin2; - PRCList *end1; - PRCList *end2; - - if (list1 == NULL){ - return list2; - } else if (list2 == NULL) { - return list1; - } else { - begin1 = &list1->l; - begin2 = &list2->l; - end1 = list1->l.prev; - end2 = list2->l.prev; - end1->next = begin2; - end2->next = begin1; - begin1->prev = end2; - begin2->prev = end1; - return list1; - } -} - - -CERTNameConstraint * -cert_CombineConstraintsLists(CERTNameConstraint *list1, CERTNameConstraint *list2) -{ - PRCList *begin1; - PRCList *begin2; - PRCList *end1; - PRCList *end2; - - if (list1 == NULL){ - return list2; - } else if (list2 == NULL) { - return list1; - } else { - begin1 = &list1->l; - begin2 = &list2->l; - end1 = list1->l.prev; - end2 = list2->l.prev; - end1->next = begin2; - end2->next = begin1; - begin1->prev = end2; - begin2->prev = end1; - return list1; - } -} - - -/* Add a CERTNameConstraint to the CERTNameConstraint list */ -CERTNameConstraint * -CERT_AddNameConstraint(CERTNameConstraint *list, - CERTNameConstraint *constraint) -{ - PORT_Assert(constraint != NULL); - constraint->l.next = constraint->l.prev = &constraint->l; - list = cert_CombineConstraintsLists(list, constraint); - return list; -} - - -SECStatus -CERT_GetNameConstraintByType (CERTNameConstraint *constraints, - CERTGeneralNameType type, - CERTNameConstraint **returnList, - PRArenaPool *arena) -{ - CERTNameConstraint *current = NULL; - void *mark = NULL; - - *returnList = NULL; - if (!constraints) - return SECSuccess; - - mark = PORT_ArenaMark(arena); - - current = constraints; - do { - PORT_Assert(current->name.type); - if (current->name.type == type) { - CERTNameConstraint *temp; - temp = CERT_CopyNameConstraint(arena, NULL, current); - if (temp == NULL) - goto loser; - *returnList = CERT_AddNameConstraint(*returnList, temp); - } - current = CERT_GetNextNameConstraint(current); - } while (current != constraints); - PORT_ArenaUnmark(arena, mark); - return SECSuccess; - -loser: - PORT_ArenaRelease(arena, mark); - return SECFailure; -} - -void * -CERT_GetGeneralNameByType (CERTGeneralName *genNames, - CERTGeneralNameType type, PRBool derFormat) -{ - CERTGeneralName *current; - - if (!genNames) - return NULL; - current = genNames; - - do { - if (current->type == type) { - switch (type) { - case certDNSName: - case certEDIPartyName: - case certIPAddress: - case certRegisterID: - case certRFC822Name: - case certX400Address: - case certURI: - return (void *)¤t->name.other; /* SECItem * */ - - case certOtherName: - return (void *)¤t->name.OthName; /* OthName * */ - - case certDirectoryName: - return derFormat - ? (void *)¤t->derDirectoryName /* SECItem * */ - : (void *)¤t->name.directoryName; /* CERTName * */ - } - PORT_Assert(0); - return NULL; - } - current = CERT_GetNextGeneralName(current); - } while (current != genNames); - return NULL; -} - -int -CERT_GetNamesLength(CERTGeneralName *names) -{ - int length = 0; - CERTGeneralName *first; - - first = names; - if (names != NULL) { - do { - length++; - names = CERT_GetNextGeneralName(names); - } while (names != first); - } - return length; -} - -/* Creates new GeneralNames for any email addresses found in the -** input DN, and links them onto the list for the DN. -*/ -SECStatus -cert_ExtractDNEmailAddrs(CERTGeneralName *name, PLArenaPool *arena) -{ - CERTGeneralName *nameList = NULL; - const CERTRDN **nRDNs = (const CERTRDN **)(name->name.directoryName.rdns); - SECStatus rv = SECSuccess; - - PORT_Assert(name->type == certDirectoryName); - if (name->type != certDirectoryName) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - /* TODO: mark arena */ - while (nRDNs && *nRDNs) { /* loop over RDNs */ - const CERTRDN *nRDN = *nRDNs++; - CERTAVA **nAVAs = nRDN->avas; - while (nAVAs && *nAVAs) { /* loop over AVAs */ - int tag; - CERTAVA *nAVA = *nAVAs++; - tag = CERT_GetAVATag(nAVA); - if ( tag == SEC_OID_PKCS9_EMAIL_ADDRESS || - tag == SEC_OID_RFC1274_MAIL) { /* email AVA */ - CERTGeneralName *newName = NULL; - SECItem *avaValue = CERT_DecodeAVAValue(&nAVA->value); - if (!avaValue) - goto loser; - rv = SECFailure; - newName = CERT_NewGeneralName(arena, certRFC822Name); - if (newName) { - rv = SECITEM_CopyItem(arena, &newName->name.other, avaValue); - } - SECITEM_FreeItem(avaValue, PR_TRUE); - if (rv != SECSuccess) - goto loser; - nameList = cert_CombineNamesLists(nameList, newName); - } /* handle one email AVA */ - } /* loop over AVAs */ - } /* loop over RDNs */ - /* combine new names with old one. */ - name = cert_CombineNamesLists(name, nameList); - /* TODO: unmark arena */ - return SECSuccess; - -loser: - /* TODO: release arena back to mark */ - return SECFailure; -} - -/* Extract all names except Subject Common Name from a cert -** in preparation for a name constraints test. -*/ -CERTGeneralName * -CERT_GetCertificateNames(CERTCertificate *cert, PRArenaPool *arena) -{ - return CERT_GetConstrainedCertificateNames(cert, arena, PR_FALSE); -} - -/* This function is called by CERT_VerifyCertChain to extract all -** names from a cert in preparation for a name constraints test. -*/ -CERTGeneralName * -CERT_GetConstrainedCertificateNames(CERTCertificate *cert, PRArenaPool *arena, - PRBool includeSubjectCommonName) -{ - CERTGeneralName *DN; - CERTGeneralName *SAN; - PRUint32 numDNSNames = 0; - SECStatus rv; - - if (!arena) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - /* TODO: mark arena */ - DN = CERT_NewGeneralName(arena, certDirectoryName); - if (DN == NULL) { - goto loser; - } - rv = CERT_CopyName(arena, &DN->name.directoryName, &cert->subject); - if (rv != SECSuccess) { - goto loser; - } - rv = SECITEM_CopyItem(arena, &DN->derDirectoryName, &cert->derSubject); - if (rv != SECSuccess) { - goto loser; - } - /* Extract email addresses from DN, construct CERTGeneralName structs - ** for them, add them to the name list - */ - rv = cert_ExtractDNEmailAddrs(DN, arena); - if (rv != SECSuccess) - goto loser; - - /* Now extract any GeneralNames from the subject name names extension. */ - SAN = cert_GetSubjectAltNameList(cert, arena); - if (SAN) { - numDNSNames = cert_CountDNSPatterns(SAN); - DN = cert_CombineNamesLists(DN, SAN); - } - if (!numDNSNames && includeSubjectCommonName) { - char *cn = CERT_GetCommonName(&cert->subject); - if (cn) { - CERTGeneralName *CN = CERT_NewGeneralName(arena, certDNSName); - if (CN) { - SECItem cnItem = {siBuffer, NULL, 0}; - cnItem.data = (unsigned char *)cn; - cnItem.len = strlen(cn); - rv = SECITEM_CopyItem(arena, &CN->name.other, &cnItem); - if (rv == SECSuccess) { - DN = cert_CombineNamesLists(DN, CN); - } - } - PORT_Free(cn); - } - } - if (rv == SECSuccess) { - /* TODO: unmark arena */ - return DN; - } -loser: - /* TODO: release arena to mark */ - return NULL; -} - -/* Returns SECSuccess if name matches constraint per RFC 3280 rules for -** URI name constraints. SECFailure otherwise. -** If the constraint begins with a dot, it is a domain name, otherwise -** It is a host name. Examples: -** Constraint Name Result -** ------------ --------------- -------- -** foo.bar.com foo.bar.com matches -** foo.bar.com FoO.bAr.CoM matches -** foo.bar.com www.foo.bar.com no match -** foo.bar.com nofoo.bar.com no match -** .foo.bar.com www.foo.bar.com matches -** .foo.bar.com nofoo.bar.com no match -** .foo.bar.com foo.bar.com no match -** .foo.bar.com www..foo.bar.com no match -*/ -static SECStatus -compareURIN2C(const SECItem *name, const SECItem *constraint) -{ - int offset; - /* The spec is silent on intepreting zero-length constraints. - ** We interpret them as matching no URI names. - */ - if (!constraint->len) - return SECFailure; - if (constraint->data[0] != '.') { - /* constraint is a host name. */ - if (name->len != constraint->len || - PL_strncasecmp((char *)name->data, - (char *)constraint->data, constraint->len)) - return SECFailure; - return SECSuccess; - } - /* constraint is a domain name. */ - if (name->len < constraint->len) - return SECFailure; - offset = name->len - constraint->len; - if (PL_strncasecmp((char *)(name->data + offset), - (char *)constraint->data, constraint->len)) - return SECFailure; - if (!offset || - (name->data[offset - 1] == '.') + (constraint->data[0] == '.') == 1) - return SECSuccess; - return SECFailure; -} - -/* for DNSname constraints, RFC 3280 says, (section 4.2.1.11, page 38) -** -** DNS name restrictions are expressed as foo.bar.com. Any DNS name -** that can be constructed by simply adding to the left hand side of the -** name satisfies the name constraint. For example, www.foo.bar.com -** would satisfy the constraint but foo1.bar.com would not. -** -** But NIST's PKITS test suite requires that the constraint be treated -** as a domain name, and requires that any name added to the left hand -** side end in a dot ".". Sensible, but not strictly following the RFC. -** -** Constraint Name RFC 3280 NIST PKITS -** ------------ --------------- -------- ---------- -** foo.bar.com foo.bar.com matches matches -** foo.bar.com FoO.bAr.CoM matches matches -** foo.bar.com www.foo.bar.com matches matches -** foo.bar.com nofoo.bar.com MATCHES NO MATCH -** .foo.bar.com www.foo.bar.com matches matches? disallowed? -** .foo.bar.com foo.bar.com no match no match -** .foo.bar.com www..foo.bar.com matches probably not -** -** We will try to conform to NIST's PKITS tests, and the unstated -** rules they imply. -*/ -static SECStatus -compareDNSN2C(const SECItem *name, const SECItem *constraint) -{ - int offset; - /* The spec is silent on intepreting zero-length constraints. - ** We interpret them as matching all DNSnames. - */ - if (!constraint->len) - return SECSuccess; - if (name->len < constraint->len) - return SECFailure; - offset = name->len - constraint->len; - if (PL_strncasecmp((char *)(name->data + offset), - (char *)constraint->data, constraint->len)) - return SECFailure; - if (!offset || - (name->data[offset - 1] == '.') + (constraint->data[0] == '.') == 1) - return SECSuccess; - return SECFailure; -} - -/* Returns SECSuccess if name matches constraint per RFC 3280 rules for -** internet email addresses. SECFailure otherwise. -** If constraint contains a '@' then the two strings much match exactly. -** Else if constraint starts with a '.'. then it must match the right-most -** substring of the name, -** else constraint string must match entire name after the name's '@'. -** Empty constraint string matches all names. All comparisons case insensitive. -*/ -static SECStatus -compareRFC822N2C(const SECItem *name, const SECItem *constraint) -{ - int offset; - if (!constraint->len) - return SECSuccess; - if (name->len < constraint->len) - return SECFailure; - if (constraint->len == 1 && constraint->data[0] == '.') - return SECSuccess; - for (offset = constraint->len - 1; offset >= 0; --offset) { - if (constraint->data[offset] == '@') { - return (name->len == constraint->len && - !PL_strncasecmp((char *)name->data, - (char *)constraint->data, constraint->len)) - ? SECSuccess : SECFailure; - } - } - offset = name->len - constraint->len; - if (PL_strncasecmp((char *)(name->data + offset), - (char *)constraint->data, constraint->len)) - return SECFailure; - if (constraint->data[0] == '.') - return SECSuccess; - if (offset > 0 && name->data[offset - 1] == '@') - return SECSuccess; - return SECFailure; -} - -/* name contains either a 4 byte IPv4 address or a 16 byte IPv6 address. -** constraint contains an address of the same length, and a subnet mask -** of the same length. Compare name's address to the constraint's -** address, subject to the mask. -** Return SECSuccess if they match, SECFailure if they don't. -*/ -static SECStatus -compareIPaddrN2C(const SECItem *name, const SECItem *constraint) -{ - int i; - if (name->len == 4 && constraint->len == 8) { /* ipv4 addr */ - for (i = 0; i < 4; i++) { - if ((name->data[i] ^ constraint->data[i]) & constraint->data[i+4]) - goto loser; - } - return SECSuccess; - } - if (name->len == 16 && constraint->len == 32) { /* ipv6 addr */ - for (i = 0; i < 16; i++) { - if ((name->data[i] ^ constraint->data[i]) & constraint->data[i+16]) - goto loser; - } - return SECSuccess; - } -loser: - return SECFailure; -} - -/* start with a SECItem that points to a URI. Parse it lookingg for -** a hostname. Modify item->data and item->len to define the hostname, -** but do not modify and data at item->data. -** If anything goes wrong, the contents of *item are undefined. -*/ -static SECStatus -parseUriHostname(SECItem * item) -{ - int i; - PRBool found = PR_FALSE; - for (i = 0; (unsigned)(i+2) < item->len; ++i) { - if (item->data[i ] == ':' && - item->data[i+1] == '/' && - item->data[i+2] == '/') { - i += 3; - item->data += i; - item->len -= i; - found = PR_TRUE; - break; - } - } - if (!found) - return SECFailure; - /* now look for a '/', which is an upper bound in the end of the name */ - for (i = 0; (unsigned)i < item->len; ++i) { - if (item->data[i] == '/') { - item->len = i; - break; - } - } - /* now look for a ':', which marks the end of the name */ - for (i = item->len; --i >= 0; ) { - if (item->data[i] == ':') { - item->len = i; - break; - } - } - /* now look for an '@', which marks the beginning of the hostname */ - for (i = 0; (unsigned)i < item->len; ++i) { - if (item->data[i] == '@') { - ++i; - item->data += i; - item->len -= i; - break; - } - } - return item->len ? SECSuccess : SECFailure; -} - -/* This function takes one name, and a list of constraints. -** It searches the constraints looking for a match. -** It returns SECSuccess if the name satisfies the constraints, i.e., -** if excluded, then the name does not match any constraint, -** if permitted, then the name matches at least one constraint. -** It returns SECFailure if the name fails to satisfy the constraints, -** or if some code fails (e.g. out of memory, or invalid constraint) -*/ -SECStatus -cert_CompareNameWithConstraints(CERTGeneralName *name, - CERTNameConstraint *constraints, - PRBool excluded) -{ - SECStatus rv = SECSuccess; - SECStatus matched = SECFailure; - CERTNameConstraint *current; - - PORT_Assert(constraints); /* caller should not call with NULL */ - if (!constraints) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - current = constraints; - do { - rv = SECSuccess; - matched = SECFailure; - PORT_Assert(name->type == current->name.type); - switch (name->type) { - - case certDNSName: - matched = compareDNSN2C(&name->name.other, - ¤t->name.name.other); - break; - - case certRFC822Name: - matched = compareRFC822N2C(&name->name.other, - ¤t->name.name.other); - break; - - case certURI: - { - /* make a modifiable copy of the URI SECItem. */ - SECItem uri = name->name.other; - /* find the hostname in the URI */ - rv = parseUriHostname(&uri); - if (rv == SECSuccess) { - /* does our hostname meet the constraint? */ - matched = compareURIN2C(&uri, ¤t->name.name.other); - } - } - break; - - case certDirectoryName: - /* Determine if the constraint directory name is a "prefix" - ** for the directory name being tested. - */ - { - /* status defaults to SECEqual, so that a constraint with - ** no AVAs will be a wildcard, matching all directory names. - */ - SECComparison status = SECEqual; - const CERTRDN **cRDNs = - (const CERTRDN **)current->name.name.directoryName.rdns; - const CERTRDN **nRDNs = - (const CERTRDN **)name->name.directoryName.rdns; - while (cRDNs && *cRDNs && nRDNs && *nRDNs) { - /* loop over name RDNs and constraint RDNs in lock step */ - const CERTRDN *cRDN = *cRDNs++; - const CERTRDN *nRDN = *nRDNs++; - CERTAVA **cAVAs = cRDN->avas; - while (cAVAs && *cAVAs) { /* loop over constraint AVAs */ - CERTAVA *cAVA = *cAVAs++; - CERTAVA **nAVAs = nRDN->avas; - while (nAVAs && *nAVAs) { /* loop over name AVAs */ - CERTAVA *nAVA = *nAVAs++; - status = CERT_CompareAVA(cAVA, nAVA); - if (status == SECEqual) - break; - } /* loop over name AVAs */ - if (status != SECEqual) - break; - } /* loop over constraint AVAs */ - if (status != SECEqual) - break; - } /* loop over name RDNs and constraint RDNs */ - matched = (status == SECEqual) ? SECSuccess : SECFailure; - break; - } - - case certIPAddress: /* type 8 */ - matched = compareIPaddrN2C(&name->name.other, - ¤t->name.name.other); - break; - - /* NSS does not know how to compare these "Other" type names with - ** their respective constraints. But it does know how to tell - ** if the constraint applies to the type of name (by comparing - ** the constraint OID to the name OID). NSS makes no use of "Other" - ** type names at all, so NSS errs on the side of leniency for these - ** types, provided that their OIDs match. So, when an "Other" - ** name constraint appears in an excluded subtree, it never causes - ** a name to fail. When an "Other" name constraint appears in a - ** permitted subtree, AND the constraint's OID matches the name's - ** OID, then name is treated as if it matches the constraint. - */ - case certOtherName: /* type 1 */ - matched = (!excluded && - name->type == current->name.type && - SECITEM_ItemsAreEqual(&name->name.OthName.oid, - ¤t->name.name.OthName.oid)) - ? SECSuccess : SECFailure; - break; - - /* NSS does not know how to compare these types of names with their - ** respective constraints. But NSS makes no use of these types of - ** names at all, so it errs on the side of leniency for these types. - ** Constraints for these types of names never cause the name to - ** fail the constraints test. NSS behaves as if the name matched - ** for permitted constraints, and did not match for excluded ones. - */ - case certX400Address: /* type 4 */ - case certEDIPartyName: /* type 6 */ - case certRegisterID: /* type 9 */ - matched = excluded ? SECFailure : SECSuccess; - break; - - default: /* non-standard types are not supported */ - rv = SECFailure; - break; - } - if (matched == SECSuccess || rv != SECSuccess) - break; - current = CERT_GetNextNameConstraint(current); - } while (current != constraints); - if (rv == SECSuccess) { - if (matched == SECSuccess) - rv = excluded ? SECFailure : SECSuccess; - else - rv = excluded ? SECSuccess : SECFailure; - return rv; - } - - return SECFailure; -} - -/* Add and link a CERTGeneralName to a CERTNameConstraint list. Most -** likely the CERTNameConstraint passed in is either the permitted -** list or the excluded list of a CERTNameConstraints. -*/ -SECStatus -CERT_AddNameConstraintByGeneralName(PLArenaPool *arena, - CERTNameConstraint **constraints, - CERTGeneralName *name) -{ - SECStatus rv; - CERTNameConstraint *current = NULL; - CERTNameConstraint *first = *constraints; - void *mark = NULL; - - mark = PORT_ArenaMark(arena); - - current = PORT_ArenaZNew(arena, CERTNameConstraint); - if (current == NULL) { - rv = SECFailure; - goto done; - } - - rv = cert_CopyOneGeneralName(arena, ¤t->name, name); - if (rv != SECSuccess) { - goto done; - } - - current->name.l.prev = current->name.l.next = &(current->name.l); - - if (first == NULL) { - *constraints = current; - PR_INIT_CLIST(¤t->l); - } else { - PR_INSERT_BEFORE(¤t->l, &first->l); - } - -done: - if (rv == SECFailure) { - PORT_ArenaRelease(arena, mark); - } else { - PORT_ArenaUnmark(arena, mark); - } - return rv; -} - -/* Extract the name constraints extension from the CA cert. */ -SECStatus -CERT_FindNameConstraintsExten(PRArenaPool *arena, - CERTCertificate *cert, - CERTNameConstraints **constraints) -{ - SECStatus rv = SECSuccess; - SECItem constraintsExtension; - void *mark = NULL; - - *constraints = NULL; - - rv = CERT_FindCertExtension(cert, SEC_OID_X509_NAME_CONSTRAINTS, - &constraintsExtension); - if (rv != SECSuccess) { - if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) { - rv = SECSuccess; - } - return rv; - } - - mark = PORT_ArenaMark(arena); - - *constraints = cert_DecodeNameConstraints(arena, &constraintsExtension); - if (*constraints == NULL) { /* decode failed */ - rv = SECFailure; - } - PORT_Free (constraintsExtension.data); - - if (rv == SECFailure) { - PORT_ArenaRelease(arena, mark); - } else { - PORT_ArenaUnmark(arena, mark); - } - - return rv; -} - -/* Verify name against all the constraints relevant to that type of -** the name. -*/ -SECStatus -CERT_CheckNameSpace(PRArenaPool *arena, - CERTNameConstraints *constraints, - CERTGeneralName *currentName) -{ - CERTNameConstraint *matchingConstraints; - SECStatus rv = SECSuccess; - - if (constraints->excluded != NULL) { - rv = CERT_GetNameConstraintByType(constraints->excluded, - currentName->type, - &matchingConstraints, arena); - if (rv == SECSuccess && matchingConstraints != NULL) { - rv = cert_CompareNameWithConstraints(currentName, - matchingConstraints, - PR_TRUE); - } - if (rv != SECSuccess) { - return(rv); - } - } - - if (constraints->permited != NULL) { - rv = CERT_GetNameConstraintByType(constraints->permited, - currentName->type, - &matchingConstraints, arena); - if (rv == SECSuccess && matchingConstraints != NULL) { - rv = cert_CompareNameWithConstraints(currentName, - matchingConstraints, - PR_FALSE); - } - if (rv != SECSuccess) { - return(rv); - } - } - - return(SECSuccess); -} - -/* Extract the name constraints extension from the CA cert. -** Test each and every name in namesList against all the constraints -** relevant to that type of name. -** Returns NULL in pBadCert for success, if all names are acceptable. -** If some name is not acceptable, returns a pointer to the cert that -** contained that name. -*/ -SECStatus -CERT_CompareNameSpace(CERTCertificate *cert, - CERTGeneralName *namesList, - CERTCertificate **certsList, - PRArenaPool *reqArena, - CERTCertificate **pBadCert) -{ - SECStatus rv = SECSuccess; - CERTNameConstraints *constraints; - CERTGeneralName *currentName; - int count = 0; - CERTCertificate *badCert = NULL; - - /* If no names to check, then no names can be bad. */ - if (!namesList) - goto done; - rv = CERT_FindNameConstraintsExten(reqArena, cert, &constraints); - if (rv != SECSuccess) { - count = -1; - goto done; - } - - currentName = namesList; - do { - if (constraints){ - rv = CERT_CheckNameSpace(reqArena, constraints, currentName); - if (rv != SECSuccess) { - break; - } - } - currentName = CERT_GetNextGeneralName(currentName); - count ++; - } while (currentName != namesList); - -done: - if (rv != SECSuccess) { - badCert = (count >= 0) ? certsList[count] : cert; - } - if (pBadCert) - *pBadCert = badCert; - - return rv; -} - -#if 0 -/* not exported from shared libs, not used. Turn on if we ever need it. */ -SECStatus -CERT_CompareGeneralName(CERTGeneralName *a, CERTGeneralName *b) -{ - CERTGeneralName *currentA; - CERTGeneralName *currentB; - PRBool found; - - currentA = a; - currentB = b; - if (a != NULL) { - do { - if (currentB == NULL) { - return SECFailure; - } - currentB = CERT_GetNextGeneralName(currentB); - currentA = CERT_GetNextGeneralName(currentA); - } while (currentA != a); - } - if (currentB != b) { - return SECFailure; - } - currentA = a; - do { - currentB = b; - found = PR_FALSE; - do { - if (currentB->type == currentA->type) { - switch (currentB->type) { - case certDNSName: - case certEDIPartyName: - case certIPAddress: - case certRegisterID: - case certRFC822Name: - case certX400Address: - case certURI: - if (SECITEM_CompareItem(¤tA->name.other, - ¤tB->name.other) - == SECEqual) { - found = PR_TRUE; - } - break; - case certOtherName: - if (SECITEM_CompareItem(¤tA->name.OthName.oid, - ¤tB->name.OthName.oid) - == SECEqual && - SECITEM_CompareItem(¤tA->name.OthName.name, - ¤tB->name.OthName.name) - == SECEqual) { - found = PR_TRUE; - } - break; - case certDirectoryName: - if (CERT_CompareName(¤tA->name.directoryName, - ¤tB->name.directoryName) - == SECEqual) { - found = PR_TRUE; - } - } - - } - currentB = CERT_GetNextGeneralName(currentB); - } while (currentB != b && found != PR_TRUE); - if (found != PR_TRUE) { - return SECFailure; - } - currentA = CERT_GetNextGeneralName(currentA); - } while (currentA != a); - return SECSuccess; -} - -SECStatus -CERT_CompareGeneralNameLists(CERTGeneralNameList *a, CERTGeneralNameList *b) -{ - SECStatus rv; - - if (a == b) { - return SECSuccess; - } - if (a != NULL && b != NULL) { - PZ_Lock(a->lock); - PZ_Lock(b->lock); - rv = CERT_CompareGeneralName(a->name, b->name); - PZ_Unlock(a->lock); - PZ_Unlock(b->lock); - } else { - rv = SECFailure; - } - return rv; -} -#endif - -#if 0 -/* This function is not exported from NSS shared libraries, and is not -** used inside of NSS. -** XXX it doesn't check for failed allocations. :-( -*/ -void * -CERT_GetGeneralNameFromListByType(CERTGeneralNameList *list, - CERTGeneralNameType type, - PRArenaPool *arena) -{ - CERTName *name = NULL; - SECItem *item = NULL; - OtherName *other = NULL; - OtherName *tmpOther = NULL; - void *data; - - PZ_Lock(list->lock); - data = CERT_GetGeneralNameByType(list->name, type, PR_FALSE); - if (data != NULL) { - switch (type) { - case certDNSName: - case certEDIPartyName: - case certIPAddress: - case certRegisterID: - case certRFC822Name: - case certX400Address: - case certURI: - if (arena != NULL) { - item = PORT_ArenaNew(arena, SECItem); - if (item != NULL) { -XXX SECITEM_CopyItem(arena, item, (SECItem *) data); - } - } else { - item = SECITEM_DupItem((SECItem *) data); - } - PZ_Unlock(list->lock); - return item; - case certOtherName: - other = (OtherName *) data; - if (arena != NULL) { - tmpOther = PORT_ArenaNew(arena, OtherName); - } else { - tmpOther = PORT_New(OtherName); - } - if (tmpOther != NULL) { -XXX SECITEM_CopyItem(arena, &tmpOther->oid, &other->oid); -XXX SECITEM_CopyItem(arena, &tmpOther->name, &other->name); - } - PZ_Unlock(list->lock); - return tmpOther; - case certDirectoryName: - if (arena) { - name = PORT_ArenaZNew(list->arena, CERTName); - if (name) { -XXX CERT_CopyName(arena, name, (CERTName *) data); - } - } - PZ_Unlock(list->lock); - return name; - } - } - PZ_Unlock(list->lock); - return NULL; -} -#endif - -#if 0 -/* This function is not exported from NSS shared libraries, and is not -** used inside of NSS. -** XXX it should NOT be a void function, since it does allocations -** that can fail. -*/ -void -CERT_AddGeneralNameToList(CERTGeneralNameList *list, - CERTGeneralNameType type, - void *data, SECItem *oid) -{ - CERTGeneralName *name; - - if (list != NULL && data != NULL) { - PZ_Lock(list->lock); - name = CERT_NewGeneralName(list->arena, type); - if (!name) - goto done; - switch (type) { - case certDNSName: - case certEDIPartyName: - case certIPAddress: - case certRegisterID: - case certRFC822Name: - case certX400Address: - case certURI: -XXX SECITEM_CopyItem(list->arena, &name->name.other, (SECItem *)data); - break; - case certOtherName: -XXX SECITEM_CopyItem(list->arena, &name->name.OthName.name, - (SECItem *) data); -XXX SECITEM_CopyItem(list->arena, &name->name.OthName.oid, - oid); - break; - case certDirectoryName: -XXX CERT_CopyName(list->arena, &name->name.directoryName, - (CERTName *) data); - break; - } - list->name = cert_CombineNamesLists(list->name, name); - list->len++; -done: - PZ_Unlock(list->lock); - } - return; -} -#endif diff --git a/security/nss/lib/certdb/genname.h b/security/nss/lib/certdb/genname.h deleted file mode 100644 index 7a05d6344..000000000 --- a/security/nss/lib/certdb/genname.h +++ /dev/null @@ -1,106 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.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 _GENAME_H_ -#define _GENAME_H_ - -#include "plarena.h" -#include "seccomon.h" -#include "secoidt.h" -#include "secasn1.h" -#include "secder.h" -#include "certt.h" - -/************************************************************************/ -SEC_BEGIN_PROTOS - -extern const SEC_ASN1Template CERT_GeneralNamesTemplate[]; - -extern SECItem ** -cert_EncodeGeneralNames(PRArenaPool *arena, CERTGeneralName *names); - -extern CERTGeneralName * -cert_DecodeGeneralNames(PRArenaPool *arena, SECItem **encodedGenName); - -extern SECStatus -cert_DestroyGeneralNames(CERTGeneralName *name); - -extern SECStatus -cert_EncodeNameConstraints(CERTNameConstraints *constraints, PRArenaPool *arena, - SECItem *dest); - -extern CERTNameConstraints * -cert_DecodeNameConstraints(PRArenaPool *arena, SECItem *encodedConstraints); - -extern CERTGeneralName * -cert_CombineNamesLists(CERTGeneralName *list1, CERTGeneralName *list2); - -extern CERTNameConstraint * -cert_CombineConstraintsLists(CERTNameConstraint *list1, CERTNameConstraint *list2); - -/*********************************************************************/ -/* A thread safe implementation of General Names */ -/*********************************************************************/ - -/* Destroy a Single CERTGeneralName */ -void -CERT_DestroyGeneralName(CERTGeneralName *name); - -SECStatus -CERT_CompareGeneralName(CERTGeneralName *a, CERTGeneralName *b); - -SECStatus -CERT_CopyGeneralName(PRArenaPool *arena, - CERTGeneralName *dest, - CERTGeneralName *src); - -/* General Name Lists are a thread safe, reference counting layer to - * general names */ - -/* Destroys a CERTGeneralNameList */ -void -CERT_DestroyGeneralNameList(CERTGeneralNameList *list); - -/* Creates a CERTGeneralNameList */ -CERTGeneralNameList * -CERT_CreateGeneralNameList(CERTGeneralName *name); - -/* Compares two CERTGeneralNameList */ -SECStatus -CERT_CompareGeneralNameLists(CERTGeneralNameList *a, CERTGeneralNameList *b); - -/* returns a copy of the first name of the type requested */ -void * -CERT_GetGeneralNameFromListByType(CERTGeneralNameList *list, - CERTGeneralNameType type, - PRArenaPool *arena); - -/* Adds a name to the tail of the list */ -void -CERT_AddGeneralNameToList(CERTGeneralNameList *list, - CERTGeneralNameType type, - void *data, SECItem *oid); - -/* returns a duplicate of the CERTGeneralNameList */ -CERTGeneralNameList * -CERT_DupGeneralNameList(CERTGeneralNameList *list); - -/* returns the number of CERTGeneralName objects in the doubly linked -** list of which *names is a member. -*/ -extern int -CERT_GetNamesLength(CERTGeneralName *names); - -/************************************************************************/ - -SECStatus -CERT_CompareNameSpace(CERTCertificate *cert, - CERTGeneralName *namesList, - CERTCertificate **certsList, - PRArenaPool *reqArena, - CERTCertificate **pBadCert); - -SEC_END_PROTOS - -#endif diff --git a/security/nss/lib/certdb/manifest.mn b/security/nss/lib/certdb/manifest.mn deleted file mode 100644 index 181da5fba..000000000 --- a/security/nss/lib/certdb/manifest.mn +++ /dev/null @@ -1,40 +0,0 @@ -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.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 = ../../.. - -EXPORTS = \ - cert.h \ - certt.h \ - certdb.h \ - $(NULL) - -PRIVATE_EXPORTS = \ - genname.h \ - xconst.h \ - certxutl.h \ - certi.h \ - $(NULL) - -MODULE = nss - -CSRCS = \ - alg1485.c \ - certdb.c \ - certv3.c \ - certxutl.c \ - crl.c \ - genname.c \ - stanpcertdb.c \ - polcyxtn.c \ - secname.c \ - xauthkid.c \ - xbsconst.c \ - xconst.c \ - $(NULL) - -LIBRARY_NAME = certdb - -# This part of the code, including all sub-dirs, can be optimized for size -export ALLOW_OPT_CODE_SIZE = 1 diff --git a/security/nss/lib/certdb/polcyxtn.c b/security/nss/lib/certdb/polcyxtn.c deleted file mode 100644 index 93de0bd60..000000000 --- a/security/nss/lib/certdb/polcyxtn.c +++ /dev/null @@ -1,828 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.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 - * - * $Id$ - */ - -#include "seccomon.h" -#include "secport.h" -#include "secder.h" -#include "cert.h" -#include "secoid.h" -#include "secasn1.h" -#include "secerr.h" -#include "nspr.h" - -SEC_ASN1_MKSUB(SEC_IntegerTemplate) -SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) - -const SEC_ASN1Template CERT_DisplayTextTypeTemplate[] = { - { SEC_ASN1_CHOICE, offsetof(SECItem, type), 0, sizeof(SECItem) }, - { SEC_ASN1_IA5_STRING, 0, 0, siAsciiString}, - { SEC_ASN1_VISIBLE_STRING , 0, 0, siVisibleString}, - { SEC_ASN1_BMP_STRING , 0, 0, siBMPString }, - { SEC_ASN1_UTF8_STRING , 0, 0, siUTF8String }, - { 0 } -}; - -const SEC_ASN1Template CERT_NoticeReferenceTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTNoticeReference) }, - { SEC_ASN1_INLINE, - offsetof(CERTNoticeReference, organization), - CERT_DisplayTextTypeTemplate, 0 }, - { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, - offsetof(CERTNoticeReference, noticeNumbers), - SEC_ASN1_SUB(SEC_IntegerTemplate) }, - { 0 } -}; - -const SEC_ASN1Template CERT_UserNoticeTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTUserNotice) }, - { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, - offsetof(CERTUserNotice, noticeReference), - CERT_NoticeReferenceTemplate, 0 }, - { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, - offsetof(CERTUserNotice, displayText), - CERT_DisplayTextTypeTemplate, 0 }, - { 0 } -}; - -const SEC_ASN1Template CERT_PolicyQualifierTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTPolicyQualifier) }, - { SEC_ASN1_OBJECT_ID, - offsetof(CERTPolicyQualifier, qualifierID) }, - { SEC_ASN1_ANY, - offsetof(CERTPolicyQualifier, qualifierValue) }, - { 0 } -}; - -const SEC_ASN1Template CERT_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), - CERT_PolicyQualifierTemplate }, - { 0 } -}; - -const SEC_ASN1Template CERT_CertificatePoliciesTemplate[] = { - { SEC_ASN1_SEQUENCE_OF, - offsetof(CERTCertificatePolicies, policyInfos), - CERT_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) } -}; - -const SEC_ASN1Template CERT_PolicyMapTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTPolicyMap) }, - { SEC_ASN1_OBJECT_ID, - offsetof(CERTPolicyMap, issuerDomainPolicy) }, - { SEC_ASN1_OBJECT_ID, - offsetof(CERTPolicyMap, subjectDomainPolicy) }, - { 0 } -}; - -const SEC_ASN1Template CERT_PolicyMappingsTemplate[] = { - { SEC_ASN1_SEQUENCE_OF, - offsetof(CERTCertificatePolicyMappings, policyMaps), - CERT_PolicyMapTemplate, sizeof(CERTPolicyMap) } -}; - -const SEC_ASN1Template CERT_PolicyConstraintsTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCertificatePolicyConstraints) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, - offsetof(CERTCertificatePolicyConstraints, explicitPolicySkipCerts), - SEC_ASN1_SUB(SEC_IntegerTemplate) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, - offsetof(CERTCertificatePolicyConstraints, inhibitMappingSkipCerts), - SEC_ASN1_SUB(SEC_IntegerTemplate) }, - { 0 } -}; - -const SEC_ASN1Template CERT_InhibitAnyTemplate[] = { - { SEC_ASN1_INTEGER, - offsetof(CERTCertificateInhibitAny, inhibitAnySkipCerts), - NULL, sizeof(CERTCertificateInhibitAny) } -}; - -static void -breakLines(char *string) -{ - char *tmpstr; - char *lastspace = NULL; - int curlen = 0; - int c; - - tmpstr = string; - - while ( ( c = *tmpstr ) != '\0' ) { - switch ( c ) { - case ' ': - lastspace = tmpstr; - break; - case '\n': - lastspace = NULL; - curlen = 0; - break; - } - - if ( ( curlen >= 55 ) && ( lastspace != NULL ) ) { - *lastspace = '\n'; - curlen = ( tmpstr - lastspace ); - lastspace = NULL; - } - - curlen++; - tmpstr++; - } - - return; -} - -CERTCertificatePolicies * -CERT_DecodeCertificatePoliciesExtension(SECItem *extnValue) -{ - PRArenaPool *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 certificate policies structure */ - policies = (CERTCertificatePolicies *) - PORT_ArenaZAlloc(arena, sizeof(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, CERT_CertificatePoliciesTemplate, - &newExtnValue); - - if ( rv != SECSuccess ) { - goto loser; - } - - /* initialize the oid tags */ - policyInfos = policies->policyInfos; - while (*policyInfos != NULL ) { - policyInfo = *policyInfos; - policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID); - policyQualifiers = policyInfo->policyQualifiers; - while ( policyQualifiers != NULL && *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); -} - -void -CERT_DestroyCertificatePoliciesExtension(CERTCertificatePolicies *policies) -{ - if ( policies != NULL ) { - PORT_FreeArena(policies->arena, PR_FALSE); - } - return; -} - -CERTCertificatePolicyMappings * -CERT_DecodePolicyMappingsExtension(SECItem *extnValue) -{ - PRArenaPool *arena = NULL; - SECStatus rv; - CERTCertificatePolicyMappings *mappings; - SECItem newExtnValue; - - /* make a new arena */ - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( !arena ) { - goto loser; - } - - /* allocate the policy mappings structure */ - mappings = (CERTCertificatePolicyMappings *) - PORT_ArenaZAlloc(arena, sizeof(CERTCertificatePolicyMappings)); - if ( mappings == NULL ) { - goto loser; - } - mappings->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 mappings */ - rv = SEC_QuickDERDecodeItem - (arena, mappings, CERT_PolicyMappingsTemplate, &newExtnValue); - if ( rv != SECSuccess ) { - goto loser; - } - - return(mappings); - -loser: - if ( arena != NULL ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -SECStatus -CERT_DestroyPolicyMappingsExtension(CERTCertificatePolicyMappings *mappings) -{ - if ( mappings != NULL ) { - PORT_FreeArena(mappings->arena, PR_FALSE); - } - return SECSuccess; -} - -SECStatus -CERT_DecodePolicyConstraintsExtension - (CERTCertificatePolicyConstraints *decodedValue, - SECItem *encodedValue) -{ - CERTCertificatePolicyConstraints decodeContext; - PRArenaPool *arena = NULL; - SECStatus rv = SECSuccess; - - /* initialize so we can tell when an optional component is omitted */ - PORT_Memset(&decodeContext, 0, sizeof(decodeContext)); - - /* make a new arena */ - arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if (!arena) { - return SECFailure; - } - - do { - /* decode the policy constraints */ - rv = SEC_QuickDERDecodeItem(arena, - &decodeContext, CERT_PolicyConstraintsTemplate, encodedValue); - - if ( rv != SECSuccess ) { - break; - } - - if (decodeContext.explicitPolicySkipCerts.len == 0) { - *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = -1; - } else { - *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = - DER_GetInteger(&decodeContext.explicitPolicySkipCerts); - } - - if (decodeContext.inhibitMappingSkipCerts.len == 0) { - *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = -1; - } else { - *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = - DER_GetInteger(&decodeContext.inhibitMappingSkipCerts); - } - - if ((*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data == - PR_INT32_MIN) || - (*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data == - PR_INT32_MAX) || - (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data == - PR_INT32_MIN) || - (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data == - PR_INT32_MAX)) { - rv = SECFailure; - } - - } while (0); - - PORT_FreeArena(arena, PR_FALSE); - return(rv); -} - -SECStatus CERT_DecodeInhibitAnyExtension - (CERTCertificateInhibitAny *decodedValue, SECItem *encodedValue) -{ - CERTCertificateInhibitAny decodeContext; - PRArenaPool *arena = NULL; - SECStatus rv = SECSuccess; - - /* make a new arena */ - arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if ( !arena ) { - return SECFailure; - } - - do { - - /* decode the policy mappings */ - decodeContext.inhibitAnySkipCerts.type = siUnsignedInteger; - rv = SEC_QuickDERDecodeItem(arena, - &decodeContext, CERT_InhibitAnyTemplate, encodedValue); - - if ( rv != SECSuccess ) { - break; - } - - *(PRInt32 *)decodedValue->inhibitAnySkipCerts.data = - DER_GetInteger(&decodeContext.inhibitAnySkipCerts); - - } while (0); - - PORT_FreeArena(arena, PR_FALSE); - return(rv); -} - -CERTUserNotice * -CERT_DecodeUserNotice(SECItem *noticeItem) -{ - PRArenaPool *arena = NULL; - SECStatus rv; - CERTUserNotice *userNotice; - SECItem newNoticeItem; - - /* make a new arena */ - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - - if ( !arena ) { - goto loser; - } - - /* allocate the userNotice structure */ - userNotice = (CERTUserNotice *)PORT_ArenaZAlloc(arena, - sizeof(CERTUserNotice)); - - if ( userNotice == NULL ) { - goto loser; - } - - userNotice->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, &newNoticeItem, noticeItem); - if ( rv != SECSuccess ) { - goto loser; - } - - /* decode the user notice */ - rv = SEC_QuickDERDecodeItem(arena, userNotice, CERT_UserNoticeTemplate, - &newNoticeItem); - - if ( rv != SECSuccess ) { - goto loser; - } - - if (userNotice->derNoticeReference.data != NULL) { - - rv = SEC_QuickDERDecodeItem(arena, &userNotice->noticeReference, - CERT_NoticeReferenceTemplate, - &userNotice->derNoticeReference); - if (rv == SECFailure) { - goto loser; - } - } - - return(userNotice); - -loser: - if ( arena != NULL ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(NULL); -} - -void -CERT_DestroyUserNotice(CERTUserNotice *userNotice) -{ - if ( userNotice != NULL ) { - PORT_FreeArena(userNotice->arena, PR_FALSE); - } - return; -} - -static CERTPolicyStringCallback policyStringCB = NULL; -static void *policyStringCBArg = NULL; - -void -CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg) -{ - policyStringCB = cb; - policyStringCBArg = cbarg; - return; -} - -char * -stringFromUserNotice(SECItem *noticeItem) -{ - SECItem *org; - unsigned int len, headerlen; - char *stringbuf; - CERTUserNotice *userNotice; - char *policystr; - char *retstr = NULL; - SECItem *displayText; - SECItem **noticeNumbers; - unsigned int strnum; - - /* decode the user notice */ - userNotice = CERT_DecodeUserNotice(noticeItem); - if ( userNotice == NULL ) { - return(NULL); - } - - org = &userNotice->noticeReference.organization; - if ( (org->len != 0 ) && ( policyStringCB != NULL ) ) { - /* has a noticeReference */ - - /* extract the org string */ - len = org->len; - stringbuf = (char*)PORT_Alloc(len + 1); - if ( stringbuf != NULL ) { - PORT_Memcpy(stringbuf, org->data, len); - stringbuf[len] = '\0'; - - noticeNumbers = userNotice->noticeReference.noticeNumbers; - while ( *noticeNumbers != NULL ) { - /* XXX - only one byte integers right now*/ - strnum = (*noticeNumbers)->data[0]; - policystr = (* policyStringCB)(stringbuf, - strnum, - policyStringCBArg); - if ( policystr != NULL ) { - if ( retstr != NULL ) { - retstr = PR_sprintf_append(retstr, "\n%s", policystr); - } else { - retstr = PR_sprintf_append(retstr, "%s", policystr); - } - - PORT_Free(policystr); - } - - noticeNumbers++; - } - - PORT_Free(stringbuf); - } - } - - if ( retstr == NULL ) { - if ( userNotice->displayText.len != 0 ) { - displayText = &userNotice->displayText; - - if ( displayText->len > 2 ) { - if ( displayText->data[0] == SEC_ASN1_VISIBLE_STRING ) { - headerlen = 2; - if ( displayText->data[1] & 0x80 ) { - /* multibyte length */ - headerlen += ( displayText->data[1] & 0x7f ); - } - - len = displayText->len - headerlen; - retstr = (char*)PORT_Alloc(len + 1); - if ( retstr != NULL ) { - PORT_Memcpy(retstr, &displayText->data[headerlen],len); - retstr[len] = '\0'; - } - } - } - } - } - - CERT_DestroyUserNotice(userNotice); - - return(retstr); -} - -char * -CERT_GetCertCommentString(CERTCertificate *cert) -{ - char *retstring = NULL; - SECStatus rv; - SECItem policyItem; - CERTCertificatePolicies *policies = NULL; - CERTPolicyInfo **policyInfos; - CERTPolicyQualifier **policyQualifiers, *qualifier; - - policyItem.data = NULL; - - rv = CERT_FindCertExtension(cert, SEC_OID_X509_CERTIFICATE_POLICIES, - &policyItem); - if ( rv != SECSuccess ) { - goto nopolicy; - } - - policies = CERT_DecodeCertificatePoliciesExtension(&policyItem); - if ( policies == NULL ) { - goto nopolicy; - } - - policyInfos = policies->policyInfos; - /* search through policyInfos looking for the verisign policy */ - while (*policyInfos != NULL ) { - if ( (*policyInfos)->oid == SEC_OID_VERISIGN_USER_NOTICES ) { - policyQualifiers = (*policyInfos)->policyQualifiers; - /* search through the policy qualifiers looking for user notice */ - while ( policyQualifiers != NULL && *policyQualifiers != NULL ) { - qualifier = *policyQualifiers; - if ( qualifier->oid == SEC_OID_PKIX_USER_NOTICE_QUALIFIER ) { - retstring = - stringFromUserNotice(&qualifier->qualifierValue); - break; - } - - policyQualifiers++; - } - break; - } - policyInfos++; - } - -nopolicy: - if ( policyItem.data != NULL ) { - PORT_Free(policyItem.data); - } - - if ( policies != NULL ) { - CERT_DestroyCertificatePoliciesExtension(policies); - } - - if ( retstring == NULL ) { - retstring = CERT_FindNSStringExtension(cert, - SEC_OID_NS_CERT_EXT_COMMENT); - } - - if ( retstring != NULL ) { - breakLines(retstring); - } - - return(retstring); -} - - -const SEC_ASN1Template CERT_OidSeqTemplate[] = { - { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, - offsetof(CERTOidSequence, oids), - SEC_ASN1_SUB(SEC_ObjectIDTemplate) } -}; - -CERTOidSequence * -CERT_DecodeOidSequence(SECItem *seqItem) -{ - PRArenaPool *arena = NULL; - SECStatus rv; - CERTOidSequence *oidSeq; - SECItem newSeqItem; - - /* make a new arena */ - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - - if ( !arena ) { - goto loser; - } - - /* allocate the userNotice structure */ - oidSeq = (CERTOidSequence *)PORT_ArenaZAlloc(arena, - sizeof(CERTOidSequence)); - - if ( oidSeq == NULL ) { - goto loser; - } - - oidSeq->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, &newSeqItem, seqItem); - if ( rv != SECSuccess ) { - goto loser; - } - - /* decode the user notice */ - rv = SEC_QuickDERDecodeItem(arena, oidSeq, CERT_OidSeqTemplate, &newSeqItem); - - if ( rv != SECSuccess ) { - goto loser; - } - - return(oidSeq); - -loser: - return(NULL); -} - - -void -CERT_DestroyOidSequence(CERTOidSequence *oidSeq) -{ - if ( oidSeq != NULL ) { - PORT_FreeArena(oidSeq->arena, PR_FALSE); - } - return; -} - -PRBool -CERT_GovtApprovedBitSet(CERTCertificate *cert) -{ - SECStatus rv; - SECItem extItem; - CERTOidSequence *oidSeq = NULL; - PRBool ret; - SECItem **oids; - SECItem *oid; - SECOidTag oidTag; - - extItem.data = NULL; - rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem); - if ( rv != SECSuccess ) { - goto loser; - } - - oidSeq = CERT_DecodeOidSequence(&extItem); - if ( oidSeq == NULL ) { - goto loser; - } - - oids = oidSeq->oids; - while ( oids != NULL && *oids != NULL ) { - oid = *oids; - - oidTag = SECOID_FindOIDTag(oid); - - if ( oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED ) { - goto success; - } - - oids++; - } - -loser: - ret = PR_FALSE; - goto done; -success: - ret = PR_TRUE; -done: - if ( oidSeq != NULL ) { - CERT_DestroyOidSequence(oidSeq); - } - if (extItem.data != NULL) { - PORT_Free(extItem.data); - } - return(ret); -} - - -SECStatus -CERT_EncodePolicyConstraintsExtension(PRArenaPool *arena, - CERTCertificatePolicyConstraints *constr, - SECItem *dest) -{ - SECStatus rv = SECSuccess; - - PORT_Assert(constr != NULL && dest != NULL); - if (constr == NULL || dest == NULL) { - return SECFailure; - } - - if (SEC_ASN1EncodeItem (arena, dest, constr, - CERT_PolicyConstraintsTemplate) == NULL) { - rv = SECFailure; - } - return(rv); -} - -SECStatus -CERT_EncodePolicyMappingExtension(PRArenaPool *arena, - CERTCertificatePolicyMappings *mapping, - SECItem *dest) -{ - SECStatus rv = SECSuccess; - - PORT_Assert(mapping != NULL && dest != NULL); - if (mapping == NULL || dest == NULL) { - return SECFailure; - } - - if (SEC_ASN1EncodeItem (arena, dest, mapping, - CERT_PolicyMappingsTemplate) == NULL) { - rv = SECFailure; - } - return(rv); -} - - - -SECStatus -CERT_EncodeCertPoliciesExtension(PRArenaPool *arena, - CERTPolicyInfo **info, - SECItem *dest) -{ - SECStatus rv = SECSuccess; - - PORT_Assert(info != NULL && dest != NULL); - if (info == NULL || dest == NULL) { - return SECFailure; - } - - if (SEC_ASN1EncodeItem (arena, dest, info, - CERT_CertificatePoliciesTemplate) == NULL) { - rv = SECFailure; - } - return(rv); -} - -SECStatus -CERT_EncodeUserNotice(PRArenaPool *arena, - CERTUserNotice *notice, - SECItem *dest) -{ - SECStatus rv = SECSuccess; - - PORT_Assert(notice != NULL && dest != NULL); - if (notice == NULL || dest == NULL) { - return SECFailure; - } - - if (SEC_ASN1EncodeItem(arena, dest, - notice, CERT_UserNoticeTemplate) == NULL) { - rv = SECFailure; - } - - return(rv); -} - -SECStatus -CERT_EncodeNoticeReference(PRArenaPool *arena, - CERTNoticeReference *reference, - SECItem *dest) -{ - SECStatus rv = SECSuccess; - - PORT_Assert(reference != NULL && dest != NULL); - if (reference == NULL || dest == NULL) { - return SECFailure; - } - - if (SEC_ASN1EncodeItem (arena, dest, reference, - CERT_NoticeReferenceTemplate) == NULL) { - rv = SECFailure; - } - - return(rv); -} - -SECStatus -CERT_EncodeInhibitAnyExtension(PRArenaPool *arena, - CERTCertificateInhibitAny *certInhibitAny, - SECItem *dest) -{ - SECStatus rv = SECSuccess; - - PORT_Assert(certInhibitAny != NULL && dest != NULL); - if (certInhibitAny == NULL || dest == NULL) { - return SECFailure; - } - - if (SEC_ASN1EncodeItem (arena, dest, certInhibitAny, - CERT_InhibitAnyTemplate) == NULL) { - rv = SECFailure; - } - return(rv); -} diff --git a/security/nss/lib/certdb/secname.c b/security/nss/lib/certdb/secname.c deleted file mode 100644 index 7800099f8..000000000 --- a/security/nss/lib/certdb/secname.c +++ /dev/null @@ -1,709 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.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 "cert.h" -#include "secoid.h" -#include "secder.h" /* XXX remove this when remove the DERTemplates */ -#include "secasn1.h" -#include "secitem.h" -#include <stdarg.h> -#include "secerr.h" -#include "certi.h" - -static const SEC_ASN1Template cert_AVATemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTAVA) }, - { SEC_ASN1_OBJECT_ID, - offsetof(CERTAVA,type), }, - { SEC_ASN1_ANY, - offsetof(CERTAVA,value), }, - { 0, } -}; - -const SEC_ASN1Template CERT_RDNTemplate[] = { - { SEC_ASN1_SET_OF, - offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) } -}; - - -static int -CountArray(void **array) -{ - int count = 0; - if (array) { - while (*array++) { - count++; - } - } - return count; -} - -static void ** -AddToArray(PRArenaPool *arena, void **array, void *element) -{ - unsigned count; - void **ap; - - /* Count up number of slots already in use in the array */ - count = 0; - ap = array; - if (ap) { - while (*ap++) { - count++; - } - } - - if (array) { - array = (void**) PORT_ArenaGrow(arena, array, - (count + 1) * sizeof(void *), - (count + 2) * sizeof(void *)); - } else { - array = (void**) PORT_ArenaAlloc(arena, (count + 2) * sizeof(void *)); - } - if (array) { - array[count] = element; - array[count+1] = 0; - } - return array; -} - - -SECOidTag -CERT_GetAVATag(CERTAVA *ava) -{ - SECOidData *oid; - if (!ava->type.data) return (SECOidTag)-1; - - oid = SECOID_FindOID(&ava->type); - - if ( oid ) { - return(oid->offset); - } - return (SECOidTag)-1; -} - -static SECStatus -SetupAVAType(PRArenaPool *arena, SECOidTag type, SECItem *it, unsigned *maxLenp) -{ - unsigned char *oid; - unsigned oidLen; - unsigned char *cp; - int maxLen; - SECOidData *oidrec; - - oidrec = SECOID_FindOIDByTag(type); - if (oidrec == NULL) - return SECFailure; - - oid = oidrec->oid.data; - oidLen = oidrec->oid.len; - - maxLen = cert_AVAOidTagToMaxLen(type); - if (maxLen < 0) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - it->data = cp = (unsigned char*) PORT_ArenaAlloc(arena, oidLen); - if (cp == NULL) { - return SECFailure; - } - it->len = oidLen; - PORT_Memcpy(cp, oid, oidLen); - *maxLenp = (unsigned)maxLen; - return SECSuccess; -} - -static SECStatus -SetupAVAValue(PRArenaPool *arena, int valueType, const SECItem *in, - SECItem *out, unsigned maxLen) -{ - PRUint8 *value, *cp, *ucs4Val; - unsigned valueLen, valueLenLen, total; - unsigned ucs4Len = 0, ucs4MaxLen; - - value = in->data; - valueLen = in->len; - switch (valueType) { - case SEC_ASN1_PRINTABLE_STRING: - case SEC_ASN1_IA5_STRING: - case SEC_ASN1_T61_STRING: - case SEC_ASN1_UTF8_STRING: /* no conversion required */ - break; - case SEC_ASN1_UNIVERSAL_STRING: - ucs4MaxLen = valueLen * 6; - ucs4Val = (PRUint8 *)PORT_ArenaZAlloc(arena, ucs4MaxLen); - if(!ucs4Val || !PORT_UCS4_UTF8Conversion(PR_TRUE, value, valueLen, - ucs4Val, ucs4MaxLen, &ucs4Len)) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - value = ucs4Val; - valueLen = ucs4Len; - maxLen *= 4; - break; - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - if (valueLen > maxLen) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - valueLenLen = DER_LengthLength(valueLen); - total = 1 + valueLenLen + valueLen; - cp = (PRUint8*)PORT_ArenaAlloc(arena, total); - if (!cp) { - return SECFailure; - } - out->data = cp; - out->len = total; - cp = (PRUint8 *)DER_StoreHeader(cp, valueType, valueLen); - PORT_Memcpy(cp, value, valueLen); - return SECSuccess; -} - -CERTAVA * -CERT_CreateAVAFromRaw(PRArenaPool *pool, const SECItem * OID, - const SECItem * value) -{ - CERTAVA *ava; - int rv; - - ava = PORT_ArenaZNew(pool, CERTAVA); - if (ava) { - rv = SECITEM_CopyItem(pool, &ava->type, OID); - if (rv) - return NULL; - - rv = SECITEM_CopyItem(pool, &ava->value, value); - if (rv) - return NULL; - } - return ava; -} - -CERTAVA * -CERT_CreateAVAFromSECItem(PRArenaPool *arena, SECOidTag kind, int valueType, - SECItem *value) -{ - CERTAVA *ava; - int rv; - unsigned maxLen; - - ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA)); - if (ava) { - rv = SetupAVAType(arena, kind, &ava->type, &maxLen); - if (rv) { - /* Illegal AVA type */ - return NULL; - } - rv = SetupAVAValue(arena, valueType, value, &ava->value, maxLen); - if (rv) { - /* Illegal value type */ - return NULL; - } - } - return ava; -} - -CERTAVA * -CERT_CreateAVA(PRArenaPool *arena, SECOidTag kind, int valueType, char *value) -{ - SECItem item = { siBuffer, NULL, 0 }; - - item.data = (PRUint8 *)value; - item.len = PORT_Strlen(value); - - return CERT_CreateAVAFromSECItem(arena, kind, valueType, &item); -} - -CERTAVA * -CERT_CopyAVA(PRArenaPool *arena, CERTAVA *from) -{ - CERTAVA *ava; - int rv; - - ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA)); - if (ava) { - rv = SECITEM_CopyItem(arena, &ava->type, &from->type); - if (rv) goto loser; - rv = SECITEM_CopyItem(arena, &ava->value, &from->value); - if (rv) goto loser; - } - return ava; - - loser: - return 0; -} - -/************************************************************************/ -/* XXX This template needs to go away in favor of the new SEC_ASN1 version. */ -static const SEC_ASN1Template cert_RDNTemplate[] = { - { SEC_ASN1_SET_OF, - offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) } -}; - - -CERTRDN * -CERT_CreateRDN(PRArenaPool *arena, CERTAVA *ava0, ...) -{ - CERTAVA *ava; - CERTRDN *rdn; - va_list ap; - unsigned count; - CERTAVA **avap; - - rdn = (CERTRDN*) PORT_ArenaAlloc(arena, sizeof(CERTRDN)); - if (rdn) { - /* Count number of avas going into the rdn */ - count = 0; - if (ava0) { - count++; - va_start(ap, ava0); - while ((ava = va_arg(ap, CERTAVA*)) != 0) { - count++; - } - va_end(ap); - } - - /* Now fill in the pointers */ - rdn->avas = avap = - (CERTAVA**) PORT_ArenaAlloc( arena, (count + 1)*sizeof(CERTAVA*)); - if (!avap) { - return 0; - } - if (ava0) { - *avap++ = ava0; - va_start(ap, ava0); - while ((ava = va_arg(ap, CERTAVA*)) != 0) { - *avap++ = ava; - } - va_end(ap); - } - *avap++ = 0; - } - return rdn; -} - -SECStatus -CERT_AddAVA(PRArenaPool *arena, CERTRDN *rdn, CERTAVA *ava) -{ - rdn->avas = (CERTAVA**) AddToArray(arena, (void**) rdn->avas, ava); - return rdn->avas ? SECSuccess : SECFailure; -} - -SECStatus -CERT_CopyRDN(PRArenaPool *arena, CERTRDN *to, CERTRDN *from) -{ - CERTAVA **avas, *fava, *tava; - SECStatus rv = SECSuccess; - - /* Copy each ava from from */ - avas = from->avas; - if (avas) { - if (avas[0] == NULL) { - rv = CERT_AddAVA(arena, to, NULL); - return rv; - } - while ((fava = *avas++) != 0) { - tava = CERT_CopyAVA(arena, fava); - if (!tava) { - rv = SECFailure; - break; - } - rv = CERT_AddAVA(arena, to, tava); - if (rv != SECSuccess) - break; - } - } - return rv; -} - -/************************************************************************/ - -const SEC_ASN1Template CERT_NameTemplate[] = { - { SEC_ASN1_SEQUENCE_OF, - offsetof(CERTName,rdns), CERT_RDNTemplate, sizeof(CERTName) } -}; - -SEC_ASN1_CHOOSER_IMPLEMENT(CERT_NameTemplate) - -CERTName * -CERT_CreateName(CERTRDN *rdn0, ...) -{ - CERTRDN *rdn; - CERTName *name; - va_list ap; - unsigned count; - CERTRDN **rdnp; - PRArenaPool *arena; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( !arena ) { - return(0); - } - - name = (CERTName*) PORT_ArenaAlloc(arena, sizeof(CERTName)); - if (name) { - name->arena = arena; - - /* Count number of RDNs going into the Name */ - if (!rdn0) { - count = 0; - } else { - count = 1; - va_start(ap, rdn0); - while ((rdn = va_arg(ap, CERTRDN*)) != 0) { - count++; - } - va_end(ap); - } - - /* Allocate space (including space for terminal null ptr) */ - name->rdns = rdnp = - (CERTRDN**) PORT_ArenaAlloc(arena, (count + 1) * sizeof(CERTRDN*)); - if (!name->rdns) { - goto loser; - } - - /* Now fill in the pointers */ - if (count > 0) { - *rdnp++ = rdn0; - va_start(ap, rdn0); - while ((rdn = va_arg(ap, CERTRDN*)) != 0) { - *rdnp++ = rdn; - } - va_end(ap); - } - - /* null terminate the list */ - *rdnp++ = 0; - } - return name; - -loser: - PORT_FreeArena(arena, PR_FALSE); - return(0); -} - -void -CERT_DestroyName(CERTName *name) -{ - if (name) - { - PRArenaPool *arena = name->arena; - name->rdns = NULL; - name->arena = NULL; - if (arena) PORT_FreeArena(arena, PR_FALSE); - } -} - -SECStatus -CERT_AddRDN(CERTName *name, CERTRDN *rdn) -{ - name->rdns = (CERTRDN**) AddToArray(name->arena, (void**) name->rdns, rdn); - return name->rdns ? SECSuccess : SECFailure; -} - -SECStatus -CERT_CopyName(PRArenaPool *arena, CERTName *to, CERTName *from) -{ - CERTRDN **rdns, *frdn, *trdn; - SECStatus rv = SECSuccess; - - if (!to || !from) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - CERT_DestroyName(to); - to->arena = arena; - - /* Copy each rdn from from */ - rdns = from->rdns; - if (rdns) { - if (rdns[0] == NULL) { - rv = CERT_AddRDN(to, NULL); - return rv; - } - while ((frdn = *rdns++) != NULL) { - trdn = CERT_CreateRDN(arena, NULL); - if (!trdn) { - rv = SECFailure; - break; - } - rv = CERT_CopyRDN(arena, trdn, frdn); - if (rv != SECSuccess) - break; - rv = CERT_AddRDN(to, trdn); - if (rv != SECSuccess) - break; - } - } - return rv; -} - -/************************************************************************/ - -static void -canonicalize(SECItem * foo) -{ - int ch, lastch, len, src, dest; - - /* strip trailing whitespace. */ - len = foo->len; - while (len > 0 && ((ch = foo->data[len - 1]) == ' ' || - ch == '\t' || ch == '\r' || ch == '\n')) { - len--; - } - - src = 0; - /* strip leading whitespace. */ - while (src < len && ((ch = foo->data[src]) == ' ' || - ch == '\t' || ch == '\r' || ch == '\n')) { - src++; - } - dest = 0; lastch = ' '; - while (src < len) { - ch = foo->data[src++]; - if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') { - ch = ' '; - if (ch == lastch) - continue; - } else if (ch >= 'A' && ch <= 'Z') { - ch |= 0x20; /* downshift */ - } - foo->data[dest++] = lastch = ch; - } - foo->len = dest; -} - -/* SECItems a and b contain DER-encoded printable strings. */ -SECComparison -CERT_CompareDERPrintableStrings(const SECItem *a, const SECItem *b) -{ - SECComparison rv = SECLessThan; - SECItem * aVal = CERT_DecodeAVAValue(a); - SECItem * bVal = CERT_DecodeAVAValue(b); - - if (aVal && aVal->len && aVal->data && - bVal && bVal->len && bVal->data) { - canonicalize(aVal); - canonicalize(bVal); - rv = SECITEM_CompareItem(aVal, bVal); - } - SECITEM_FreeItem(aVal, PR_TRUE); - SECITEM_FreeItem(bVal, PR_TRUE); - return rv; -} - -SECComparison -CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b) -{ - SECComparison rv; - - rv = SECITEM_CompareItem(&a->type, &b->type); - if (SECEqual != rv) - return rv; /* Attribute types don't match. */ - /* Let's be optimistic. Maybe the values will just compare equal. */ - rv = SECITEM_CompareItem(&a->value, &b->value); - if (SECEqual == rv) - return rv; /* values compared exactly. */ - if (a->value.len && a->value.data && b->value.len && b->value.data) { - /* Here, the values did not match. - ** If the values had different encodings, convert them to the same - ** encoding and compare that way. - */ - if (a->value.data[0] != b->value.data[0]) { - /* encodings differ. Convert both to UTF-8 and compare. */ - SECItem * aVal = CERT_DecodeAVAValue(&a->value); - SECItem * bVal = CERT_DecodeAVAValue(&b->value); - if (aVal && aVal->len && aVal->data && - bVal && bVal->len && bVal->data) { - rv = SECITEM_CompareItem(aVal, bVal); - } - SECITEM_FreeItem(aVal, PR_TRUE); - SECITEM_FreeItem(bVal, PR_TRUE); - } else if (a->value.data[0] == 0x13) { /* both are printable strings. */ - /* printable strings */ - rv = CERT_CompareDERPrintableStrings(&a->value, &b->value); - } - } - return rv; -} - -SECComparison -CERT_CompareRDN(const CERTRDN *a, const CERTRDN *b) -{ - CERTAVA **aavas, *aava; - CERTAVA **bavas, *bava; - int ac, bc; - SECComparison rv = SECEqual; - - aavas = a->avas; - bavas = b->avas; - - /* - ** Make sure array of ava's are the same length. If not, then we are - ** not equal - */ - ac = CountArray((void**) aavas); - bc = CountArray((void**) bavas); - if (ac < bc) return SECLessThan; - if (ac > bc) return SECGreaterThan; - - while (NULL != (aava = *aavas++)) { - for (bavas = b->avas; NULL != (bava = *bavas++); ) { - rv = SECITEM_CompareItem(&aava->type, &bava->type); - if (SECEqual == rv) { - rv = CERT_CompareAVA(aava, bava); - if (SECEqual != rv) - return rv; - break; - } - } - if (!bava) /* didn't find a match */ - return SECGreaterThan; - } - return rv; -} - -SECComparison -CERT_CompareName(const CERTName *a, const CERTName *b) -{ - CERTRDN **ardns, *ardn; - CERTRDN **brdns, *brdn; - int ac, bc; - SECComparison rv = SECEqual; - - ardns = a->rdns; - brdns = b->rdns; - - /* - ** Make sure array of rdn's are the same length. If not, then we are - ** not equal - */ - ac = CountArray((void**) ardns); - bc = CountArray((void**) brdns); - if (ac < bc) return SECLessThan; - if (ac > bc) return SECGreaterThan; - - for (;;) { - ardn = *ardns++; - brdn = *brdns++; - if (!ardn) { - break; - } - rv = CERT_CompareRDN(ardn, brdn); - if (rv) return rv; - } - return rv; -} - -/* Moved from certhtml.c */ -SECItem * -CERT_DecodeAVAValue(const SECItem *derAVAValue) -{ - SECItem *retItem; - const SEC_ASN1Template *theTemplate = NULL; - enum { conv_none, conv_ucs4, conv_ucs2, conv_iso88591 } convert = conv_none; - SECItem avaValue = {siBuffer, 0}; - PLArenaPool *newarena = NULL; - - if (!derAVAValue || !derAVAValue->len || !derAVAValue->data) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - - switch(derAVAValue->data[0]) { - case SEC_ASN1_UNIVERSAL_STRING: - convert = conv_ucs4; - theTemplate = SEC_ASN1_GET(SEC_UniversalStringTemplate); - break; - case SEC_ASN1_IA5_STRING: - theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate); - break; - case SEC_ASN1_PRINTABLE_STRING: - theTemplate = SEC_ASN1_GET(SEC_PrintableStringTemplate); - break; - case SEC_ASN1_T61_STRING: - /* - * Per common practice, we're not decoding actual T.61, but instead - * treating T61-labeled strings as containing ISO-8859-1. - */ - convert = conv_iso88591; - theTemplate = SEC_ASN1_GET(SEC_T61StringTemplate); - break; - case SEC_ASN1_BMP_STRING: - convert = conv_ucs2; - theTemplate = SEC_ASN1_GET(SEC_BMPStringTemplate); - break; - case SEC_ASN1_UTF8_STRING: - /* No conversion needed ! */ - theTemplate = SEC_ASN1_GET(SEC_UTF8StringTemplate); - break; - default: - PORT_SetError(SEC_ERROR_INVALID_AVA); - return NULL; - } - - PORT_Memset(&avaValue, 0, sizeof(SECItem)); - newarena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (!newarena) { - return NULL; - } - if(SEC_QuickDERDecodeItem(newarena, &avaValue, theTemplate, derAVAValue) - != SECSuccess) { - PORT_FreeArena(newarena, PR_FALSE); - return NULL; - } - - if (convert != conv_none) { - unsigned int utf8ValLen = avaValue.len * 3; - unsigned char *utf8Val = (unsigned char*) - PORT_ArenaZAlloc(newarena, utf8ValLen); - - switch (convert) { - case conv_ucs4: - if(avaValue.len % 4 != 0 || - !PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, - utf8Val, utf8ValLen, &utf8ValLen)) { - PORT_FreeArena(newarena, PR_FALSE); - PORT_SetError(SEC_ERROR_INVALID_AVA); - return NULL; - } - break; - case conv_ucs2: - if(avaValue.len % 2 != 0 || - !PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, - utf8Val, utf8ValLen, &utf8ValLen)) { - PORT_FreeArena(newarena, PR_FALSE); - PORT_SetError(SEC_ERROR_INVALID_AVA); - return NULL; - } - break; - case conv_iso88591: - if(!PORT_ISO88591_UTF8Conversion(avaValue.data, avaValue.len, - utf8Val, utf8ValLen, &utf8ValLen)) { - PORT_FreeArena(newarena, PR_FALSE); - PORT_SetError(SEC_ERROR_INVALID_AVA); - return NULL; - } - break; - case conv_none: - PORT_Assert(0); /* not reached */ - break; - } - - avaValue.data = utf8Val; - avaValue.len = utf8ValLen; - } - - retItem = SECITEM_DupItem(&avaValue); - PORT_FreeArena(newarena, PR_FALSE); - return retItem; -} diff --git a/security/nss/lib/certdb/stanpcertdb.c b/security/nss/lib/certdb/stanpcertdb.c deleted file mode 100644 index ce20b6f0b..000000000 --- a/security/nss/lib/certdb/stanpcertdb.c +++ /dev/null @@ -1,1071 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.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 "prtime.h" - -#include "cert.h" -#include "certi.h" -#include "certdb.h" -#include "secitem.h" -#include "secder.h" - -/* Call to PK11_FreeSlot below */ - -#include "secasn1.h" -#include "secerr.h" -#include "nssilock.h" -#include "prmon.h" -#include "base64.h" -#include "sechash.h" -#include "plhash.h" -#include "pk11func.h" /* sigh */ - -#include "nsspki.h" -#include "pki.h" -#include "pkim.h" -#include "pki3hack.h" -#include "ckhelper.h" -#include "base.h" -#include "pkistore.h" -#include "dev3hack.h" -#include "dev.h" - -PRBool -SEC_CertNicknameConflict(const char *nickname, SECItem *derSubject, - CERTCertDBHandle *handle) -{ - CERTCertificate *cert; - PRBool conflict = PR_FALSE; - - cert=CERT_FindCertByNickname(handle, nickname); - - if (!cert) { - return conflict; - } - - conflict = !SECITEM_ItemsAreEqual(derSubject,&cert->derSubject); - CERT_DestroyCertificate(cert); - return conflict; -} - -SECStatus -SEC_DeletePermCertificate(CERTCertificate *cert) -{ - PRStatus nssrv; - NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); - NSSCertificate *c = STAN_GetNSSCertificate(cert); - CERTCertTrust *certTrust; - - if (c == NULL) { - /* error code is set */ - return SECFailure; - } - - certTrust = nssTrust_GetCERTCertTrustForCert(c, cert); - if (certTrust) { - NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c); - if (nssTrust) { - nssrv = STAN_DeleteCertTrustMatchingSlot(c); - if (nssrv != PR_SUCCESS) { - CERT_MapStanError(); - } - /* This call always returns PR_SUCCESS! */ - (void) nssTrust_Destroy(nssTrust); - } - } - - /* get rid of the token instances */ - nssrv = NSSCertificate_DeleteStoredObject(c, NULL); - - /* get rid of the cache entry */ - nssTrustDomain_LockCertCache(td); - nssTrustDomain_RemoveCertFromCacheLOCKED(td, c); - nssTrustDomain_UnlockCertCache(td); - - return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; -} - -SECStatus -CERT_GetCertTrust(CERTCertificate *cert, CERTCertTrust *trust) -{ - SECStatus rv; - CERT_LockCertTrust(cert); - if ( cert->trust == NULL ) { - rv = SECFailure; - } else { - *trust = *cert->trust; - rv = SECSuccess; - } - CERT_UnlockCertTrust(cert); - return(rv); -} - -extern const NSSError NSS_ERROR_NO_ERROR; -extern const NSSError NSS_ERROR_INTERNAL_ERROR; -extern const NSSError NSS_ERROR_NO_MEMORY; -extern const NSSError NSS_ERROR_INVALID_POINTER; -extern const NSSError NSS_ERROR_INVALID_ARENA; -extern const NSSError NSS_ERROR_INVALID_ARENA_MARK; -extern const NSSError NSS_ERROR_DUPLICATE_POINTER; -extern const NSSError NSS_ERROR_POINTER_NOT_REGISTERED; -extern const NSSError NSS_ERROR_TRACKER_NOT_EMPTY; -extern const NSSError NSS_ERROR_TRACKER_NOT_INITIALIZED; -extern const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD; -extern const NSSError NSS_ERROR_VALUE_TOO_LARGE; -extern const NSSError NSS_ERROR_UNSUPPORTED_TYPE; -extern const NSSError NSS_ERROR_BUFFER_TOO_SHORT; -extern const NSSError NSS_ERROR_INVALID_ATOB_CONTEXT; -extern const NSSError NSS_ERROR_INVALID_BASE64; -extern const NSSError NSS_ERROR_INVALID_BTOA_CONTEXT; -extern const NSSError NSS_ERROR_INVALID_ITEM; -extern const NSSError NSS_ERROR_INVALID_STRING; -extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER; -extern const NSSError NSS_ERROR_INVALID_ASN1DECODER; -extern const NSSError NSS_ERROR_INVALID_BER; -extern const NSSError NSS_ERROR_INVALID_ATAV; -extern const NSSError NSS_ERROR_INVALID_ARGUMENT; -extern const NSSError NSS_ERROR_INVALID_UTF8; -extern const NSSError NSS_ERROR_INVALID_NSSOID; -extern const NSSError NSS_ERROR_UNKNOWN_ATTRIBUTE; -extern const NSSError NSS_ERROR_NOT_FOUND; -extern const NSSError NSS_ERROR_INVALID_PASSWORD; -extern const NSSError NSS_ERROR_USER_CANCELED; -extern const NSSError NSS_ERROR_MAXIMUM_FOUND; -extern const NSSError NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND; -extern const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE; -extern const NSSError NSS_ERROR_HASH_COLLISION; -extern const NSSError NSS_ERROR_DEVICE_ERROR; -extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; -extern const NSSError NSS_ERROR_BUSY; -extern const NSSError NSS_ERROR_ALREADY_INITIALIZED; -extern const NSSError NSS_ERROR_PKCS11; - - -/* Look at the stan error stack and map it to NSS 3 errors */ -#define STAN_MAP_ERROR(x,y) \ - else if (error == (x)) { \ - secError = y; \ - } \ - -/* - * map Stan errors into NSS errors - * This function examines the stan error stack and automatically sets - * PORT_SetError(); to the appropriate SEC_ERROR value. - */ -void -CERT_MapStanError() -{ - PRInt32 *errorStack; - NSSError error, prevError; - int secError; - int i; - - error = 0; - - errorStack = NSS_GetErrorStack(); - if (errorStack == 0) { - PORT_SetError(0); - return; - } - error = prevError = CKR_GENERAL_ERROR; - /* get the 'top 2' error codes from the stack */ - for (i=0; errorStack[i]; i++) { - prevError = error; - error = errorStack[i]; - } - if (error == NSS_ERROR_PKCS11) { - /* map it */ - secError = PK11_MapError(prevError); - } - STAN_MAP_ERROR(NSS_ERROR_NO_ERROR, 0) - STAN_MAP_ERROR(NSS_ERROR_NO_MEMORY, SEC_ERROR_NO_MEMORY) - STAN_MAP_ERROR(NSS_ERROR_INVALID_BASE64, SEC_ERROR_BAD_DATA) - STAN_MAP_ERROR(NSS_ERROR_INVALID_BER, SEC_ERROR_BAD_DER) - STAN_MAP_ERROR(NSS_ERROR_INVALID_ATAV, SEC_ERROR_INVALID_AVA) - STAN_MAP_ERROR(NSS_ERROR_INVALID_PASSWORD,SEC_ERROR_BAD_PASSWORD) - STAN_MAP_ERROR(NSS_ERROR_BUSY, SEC_ERROR_BUSY) - STAN_MAP_ERROR(NSS_ERROR_DEVICE_ERROR, SEC_ERROR_IO) - STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND, - SEC_ERROR_UNKNOWN_ISSUER) - STAN_MAP_ERROR(NSS_ERROR_INVALID_CERTIFICATE, SEC_ERROR_CERT_NOT_VALID) - STAN_MAP_ERROR(NSS_ERROR_INVALID_UTF8, SEC_ERROR_BAD_DATA) - STAN_MAP_ERROR(NSS_ERROR_INVALID_NSSOID, SEC_ERROR_BAD_DATA) - - /* these are library failure for lack of a better error code */ - STAN_MAP_ERROR(NSS_ERROR_NOT_FOUND, SEC_ERROR_LIBRARY_FAILURE) - STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_IN_CACHE, - SEC_ERROR_LIBRARY_FAILURE) - STAN_MAP_ERROR(NSS_ERROR_MAXIMUM_FOUND, SEC_ERROR_LIBRARY_FAILURE) - STAN_MAP_ERROR(NSS_ERROR_USER_CANCELED, SEC_ERROR_LIBRARY_FAILURE) - STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_INITIALIZED, - SEC_ERROR_LIBRARY_FAILURE) - STAN_MAP_ERROR(NSS_ERROR_ALREADY_INITIALIZED, SEC_ERROR_LIBRARY_FAILURE) - STAN_MAP_ERROR(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD, - SEC_ERROR_LIBRARY_FAILURE) - STAN_MAP_ERROR(NSS_ERROR_HASH_COLLISION, SEC_ERROR_LIBRARY_FAILURE) - - STAN_MAP_ERROR(NSS_ERROR_INTERNAL_ERROR, SEC_ERROR_LIBRARY_FAILURE) - - /* these are all invalid arguments */ - STAN_MAP_ERROR(NSS_ERROR_INVALID_ARGUMENT, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_INVALID_POINTER, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA_MARK, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_DUPLICATE_POINTER, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_POINTER_NOT_REGISTERED, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_EMPTY, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_VALUE_TOO_LARGE, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_UNSUPPORTED_TYPE, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_BUFFER_TOO_SHORT, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_INVALID_ATOB_CONTEXT, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_INVALID_BTOA_CONTEXT, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_INVALID_ITEM, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_INVALID_STRING, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1ENCODER, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1DECODER, SEC_ERROR_INVALID_ARGS) - STAN_MAP_ERROR(NSS_ERROR_UNKNOWN_ATTRIBUTE, SEC_ERROR_INVALID_ARGS) - else { - secError = SEC_ERROR_LIBRARY_FAILURE; - } - PORT_SetError(secError); -} - - - -SECStatus -CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert, - CERTCertTrust *trust) -{ - SECStatus rv = SECSuccess; - PRStatus ret; - - ret = STAN_ChangeCertTrust(cert, trust); - if (ret != PR_SUCCESS) { - rv = SECFailure; - CERT_MapStanError(); - } - return rv; -} - -extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; - -SECStatus -__CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, - CERTCertTrust *trust) -{ - NSSUTF8 *stanNick; - PK11SlotInfo *slot; - NSSToken *internal; - NSSCryptoContext *context; - nssCryptokiObject *permInstance; - NSSCertificate *c = STAN_GetNSSCertificate(cert); - nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; - nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; - SECStatus rv; - PRStatus ret; - - if (c == NULL) { - CERT_MapStanError(); - return SECFailure; - } - - context = c->object.cryptoContext; - if (!context) { - PORT_SetError(SEC_ERROR_ADDING_CERT); - return SECFailure; /* wasn't a temp cert */ - } - stanNick = nssCertificate_GetNickname(c, NULL); - if (stanNick && nickname && strcmp(nickname, stanNick) != 0) { - /* different: take the new nickname */ - cert->nickname = NULL; - nss_ZFreeIf(stanNick); - stanNick = NULL; - } - if (!stanNick && nickname) { - /* Either there was no nickname yet, or we have a new nickname */ - stanNick = nssUTF8_Duplicate((NSSUTF8 *)nickname, NULL); - } /* else: old stanNick is identical to new nickname */ - /* Delete the temp instance */ - nssCertificateStore_Lock(context->certStore, &lockTrace); - nssCertificateStore_RemoveCertLOCKED(context->certStore, c); - nssCertificateStore_Unlock(context->certStore, &lockTrace, &unlockTrace); - c->object.cryptoContext = NULL; - /* Import the perm instance onto the internal token */ - slot = PK11_GetInternalKeySlot(); - internal = PK11Slot_GetNSSToken(slot); - permInstance = nssToken_ImportCertificate(internal, NULL, - NSSCertificateType_PKIX, - &c->id, - stanNick, - &c->encoding, - &c->issuer, - &c->subject, - &c->serial, - cert->emailAddr, - PR_TRUE); - nss_ZFreeIf(stanNick); - stanNick = NULL; - PK11_FreeSlot(slot); - if (!permInstance) { - if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE) { - PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); - } - return SECFailure; - } - nssPKIObject_AddInstance(&c->object, permInstance); - nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1); - /* reset the CERTCertificate fields */ - cert->nssCertificate = NULL; - cert = STAN_GetCERTCertificateOrRelease(c); /* should return same pointer */ - if (!cert) { - CERT_MapStanError(); - return SECFailure; - } - cert->istemp = PR_FALSE; - cert->isperm = PR_TRUE; - if (!trust) { - return SECSuccess; - } - ret = STAN_ChangeCertTrust(cert, trust); - rv = SECSuccess; - if (ret != PR_SUCCESS) { - rv = SECFailure; - CERT_MapStanError(); - } - return rv; -} - -SECStatus -CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, - CERTCertTrust *trust) -{ - return __CERT_AddTempCertToPerm(cert, nickname, trust); -} - -CERTCertificate * -CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, - char *nickname, PRBool isperm, PRBool copyDER) -{ - NSSCertificate *c; - CERTCertificate *cc; - NSSCertificate *tempCert = NULL; - nssPKIObject *pkio; - NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext(); - NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain(); - if (!isperm) { - NSSDER encoding; - NSSITEM_FROM_SECITEM(&encoding, derCert); - /* First, see if it is already a temp cert */ - c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC, - &encoding); - if (!c) { - /* Then, see if it is already a perm cert */ - c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, - &encoding); - } - if (c) { - /* actually, that search ends up going by issuer/serial, - * so it is still possible to return a cert with the same - * issuer/serial but a different encoding, and we're - * going to reject that - */ - if (!nssItem_Equal(&c->encoding, &encoding, NULL)) { - nssCertificate_Destroy(c); - PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); - cc = NULL; - } else { - cc = STAN_GetCERTCertificateOrRelease(c); - if (cc == NULL) { - CERT_MapStanError(); - } - } - return cc; - } - } - pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC, nssPKIMonitor); - if (!pkio) { - CERT_MapStanError(); - return NULL; - } - c = nss_ZNEW(pkio->arena, NSSCertificate); - if (!c) { - CERT_MapStanError(); - nssPKIObject_Destroy(pkio); - return NULL; - } - c->object = *pkio; - if (copyDER) { - nssItem_Create(c->object.arena, &c->encoding, - derCert->len, derCert->data); - } else { - NSSITEM_FROM_SECITEM(&c->encoding, derCert); - } - /* Forces a decoding of the cert in order to obtain the parts used - * below - */ - /* 'c' is not adopted here, if we fail loser frees what has been - * allocated so far for 'c' */ - cc = STAN_GetCERTCertificate(c); - if (!cc) { - CERT_MapStanError(); - goto loser; - } - nssItem_Create(c->object.arena, - &c->issuer, cc->derIssuer.len, cc->derIssuer.data); - nssItem_Create(c->object.arena, - &c->subject, cc->derSubject.len, cc->derSubject.data); - if (PR_TRUE) { - /* CERTCertificate stores serial numbers decoded. I need the DER - * here. sigh. - */ - SECItem derSerial = { 0 }; - CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); - if (!derSerial.data) goto loser; - nssItem_Create(c->object.arena, &c->serial, derSerial.len, derSerial.data); - PORT_Free(derSerial.data); - } - if (nickname) { - c->object.tempName = nssUTF8_Create(c->object.arena, - nssStringType_UTF8String, - (NSSUTF8 *)nickname, - PORT_Strlen(nickname)); - } - if (cc->emailAddr && cc->emailAddr[0]) { - c->email = nssUTF8_Create(c->object.arena, - nssStringType_PrintableString, - (NSSUTF8 *)cc->emailAddr, - PORT_Strlen(cc->emailAddr)); - } - - tempCert = NSSCryptoContext_FindOrImportCertificate(gCC, c); - if (!tempCert) { - CERT_MapStanError(); - goto loser; - } - /* destroy our copy */ - NSSCertificate_Destroy(c); - /* and use the stored entry */ - c = tempCert; - cc = STAN_GetCERTCertificateOrRelease(c); - if (!cc) { - /* STAN_GetCERTCertificateOrRelease destroys c on failure. */ - CERT_MapStanError(); - return NULL; - } - - cc->istemp = PR_TRUE; - cc->isperm = PR_FALSE; - return cc; -loser: - /* Perhaps this should be nssCertificate_Destroy(c) */ - nssPKIObject_Destroy(&c->object); - return NULL; -} - -/* This symbol is exported for backward compatibility. */ -CERTCertificate * -__CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, - char *nickname, PRBool isperm, PRBool copyDER) -{ - return CERT_NewTempCertificate(handle, derCert, nickname, - isperm, copyDER); -} - -/* maybe all the wincx's should be some const for internal token login? */ -CERTCertificate * -CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN) -{ - PK11SlotInfo *slot; - CERTCertificate *cert; - - cert = PK11_FindCertByIssuerAndSN(&slot,issuerAndSN,NULL); - if (cert && slot) { - PK11_FreeSlot(slot); - } - - return cert; -} - -static NSSCertificate * -get_best_temp_or_perm(NSSCertificate *ct, NSSCertificate *cp) -{ - NSSUsage usage; - NSSCertificate *arr[3]; - if (!ct) { - return nssCertificate_AddRef(cp); - } else if (!cp) { - return nssCertificate_AddRef(ct); - } - arr[0] = ct; - arr[1] = cp; - arr[2] = NULL; - usage.anyUsage = PR_TRUE; - return nssCertificateArray_FindBestCertificate(arr, NULL, &usage, NULL); -} - -CERTCertificate * -CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name) -{ - NSSCertificate *cp, *ct, *c; - NSSDER subject; - NSSUsage usage; - NSSCryptoContext *cc; - NSSITEM_FROM_SECITEM(&subject, name); - usage.anyUsage = PR_TRUE; - cc = STAN_GetDefaultCryptoContext(); - ct = NSSCryptoContext_FindBestCertificateBySubject(cc, &subject, - NULL, &usage, NULL); - cp = NSSTrustDomain_FindBestCertificateBySubject(handle, &subject, - NULL, &usage, NULL); - c = get_best_temp_or_perm(ct, cp); - if (ct) { - CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); - } - if (cp) { - CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(cp)); - } - return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; -} - -CERTCertificate * -CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID) -{ - CERTCertList *list; - CERTCertificate *cert = NULL; - CERTCertListNode *node, *head; - - list = CERT_CreateSubjectCertList(NULL,handle,name,0,PR_FALSE); - if (list == NULL) return NULL; - - node = head = CERT_LIST_HEAD(list); - if (head) { - do { - if (node->cert && - SECITEM_ItemsAreEqual(&node->cert->subjectKeyID, keyID) ) { - cert = CERT_DupCertificate(node->cert); - goto done; - } - node = CERT_LIST_NEXT(node); - } while (node && head != node); - } - PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); -done: - if (list) { - CERT_DestroyCertList(list); - } - return cert; -} - -CERTCertificate * -CERT_FindCertByNickname(CERTCertDBHandle *handle, const char *nickname) -{ - NSSCryptoContext *cc; - NSSCertificate *c, *ct; - CERTCertificate *cert; - NSSUsage usage; - usage.anyUsage = PR_TRUE; - cc = STAN_GetDefaultCryptoContext(); - ct = NSSCryptoContext_FindBestCertificateByNickname(cc, nickname, - NULL, &usage, NULL); - cert = PK11_FindCertFromNickname(nickname, NULL); - c = NULL; - if (cert) { - c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert)); - CERT_DestroyCertificate(cert); - if (ct) { - CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); - } - } else { - c = ct; - } - return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; -} - -CERTCertificate * -CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert) -{ - NSSCryptoContext *cc; - NSSCertificate *c; - NSSDER encoding; - NSSITEM_FROM_SECITEM(&encoding, derCert); - cc = STAN_GetDefaultCryptoContext(); - c = NSSCryptoContext_FindCertificateByEncodedCertificate(cc, &encoding); - if (!c) { - c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, - &encoding); - if (!c) return NULL; - } - return STAN_GetCERTCertificateOrRelease(c); -} - -static CERTCertificate * -common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle, - const char *name, - PRBool anyUsage, - SECCertUsage lookingForUsage) -{ - NSSCryptoContext *cc; - NSSCertificate *c, *ct; - CERTCertificate *cert = NULL; - NSSUsage usage; - CERTCertList *certlist; - - if (NULL == name) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - - usage.anyUsage = anyUsage; - - if (!anyUsage) { - usage.nss3lookingForCA = PR_FALSE; - usage.nss3usage = lookingForUsage; - } - - cc = STAN_GetDefaultCryptoContext(); - ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name, - NULL, &usage, NULL); - if (!ct && PORT_Strchr(name, '@') != NULL) { - char* lowercaseName = CERT_FixupEmailAddr(name); - if (lowercaseName) { - ct = NSSCryptoContext_FindBestCertificateByEmail(cc, lowercaseName, - NULL, &usage, NULL); - PORT_Free(lowercaseName); - } - } - - if (anyUsage) { - cert = PK11_FindCertFromNickname(name, NULL); - } - else { - if (ct) { - /* Does ct really have the required usage? */ - nssDecodedCert *dc; - dc = nssCertificate_GetDecoding(ct); - if (!dc->matchUsage(dc, &usage)) { - CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); - ct = NULL; - } - } - - certlist = PK11_FindCertsFromNickname(name, NULL); - if (certlist) { - SECStatus rv = CERT_FilterCertListByUsage(certlist, - lookingForUsage, - PR_FALSE); - if (SECSuccess == rv && - !CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist)) { - cert = CERT_DupCertificate(CERT_LIST_HEAD(certlist)->cert); - } - CERT_DestroyCertList(certlist); - } - } - - if (cert) { - c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert)); - CERT_DestroyCertificate(cert); - if (ct) { - CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); - } - } else { - c = ct; - } - return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; -} - -CERTCertificate * -CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name) -{ - return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, - PR_TRUE, 0); -} - -CERTCertificate * -CERT_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle, - const char *name, - SECCertUsage lookingForUsage) -{ - return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, - PR_FALSE, - lookingForUsage); -} - -static void -add_to_subject_list(CERTCertList *certList, CERTCertificate *cert, - PRBool validOnly, int64 sorttime) -{ - SECStatus secrv; - if (!validOnly || - CERT_CheckCertValidTimes(cert, sorttime, PR_FALSE) - == secCertTimeValid) { - secrv = CERT_AddCertToListSorted(certList, cert, - CERT_SortCBValidity, - (void *)&sorttime); - if (secrv != SECSuccess) { - CERT_DestroyCertificate(cert); - } - } else { - CERT_DestroyCertificate(cert); - } -} - -CERTCertList * -CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle, - SECItem *name, int64 sorttime, PRBool validOnly) -{ - NSSCryptoContext *cc; - NSSCertificate **tSubjectCerts, **pSubjectCerts; - NSSCertificate **ci; - CERTCertificate *cert; - NSSDER subject; - PRBool myList = PR_FALSE; - cc = STAN_GetDefaultCryptoContext(); - NSSITEM_FROM_SECITEM(&subject, name); - /* Collect both temp and perm certs for the subject */ - tSubjectCerts = NSSCryptoContext_FindCertificatesBySubject(cc, - &subject, - NULL, - 0, - NULL); - pSubjectCerts = NSSTrustDomain_FindCertificatesBySubject(handle, - &subject, - NULL, - 0, - NULL); - if (!tSubjectCerts && !pSubjectCerts) { - return NULL; - } - if (certList == NULL) { - certList = CERT_NewCertList(); - myList = PR_TRUE; - if (!certList) goto loser; - } - /* Iterate over the matching temp certs. Add them to the list */ - ci = tSubjectCerts; - while (ci && *ci) { - cert = STAN_GetCERTCertificateOrRelease(*ci); - /* *ci may be invalid at this point, don't reference it again */ - if (cert) { - /* NOTE: add_to_subject_list adopts the incoming cert. */ - add_to_subject_list(certList, cert, validOnly, sorttime); - } - ci++; - } - /* Iterate over the matching perm certs. Add them to the list */ - ci = pSubjectCerts; - while (ci && *ci) { - cert = STAN_GetCERTCertificateOrRelease(*ci); - /* *ci may be invalid at this point, don't reference it again */ - if (cert) { - /* NOTE: add_to_subject_list adopts the incoming cert. */ - add_to_subject_list(certList, cert, validOnly, sorttime); - } - ci++; - } - /* all the references have been adopted or freed at this point, just - * free the arrays now */ - nss_ZFreeIf(tSubjectCerts); - nss_ZFreeIf(pSubjectCerts); - return certList; -loser: - /* need to free the references in tSubjectCerts and pSubjectCerts! */ - nssCertificateArray_Destroy(tSubjectCerts); - nssCertificateArray_Destroy(pSubjectCerts); - if (myList && certList != NULL) { - CERT_DestroyCertList(certList); - } - return NULL; -} - -void -CERT_DestroyCertificate(CERTCertificate *cert) -{ - if ( cert ) { - /* don't use STAN_GetNSSCertificate because we don't want to - * go to the trouble of translating the CERTCertificate into - * an NSSCertificate just to destroy it. If it hasn't been done - * yet, don't do it at all. - */ - NSSCertificate *tmp = cert->nssCertificate; - if (tmp) { - /* delete the NSSCertificate */ - NSSCertificate_Destroy(tmp); - } else if (cert->arena) { - PORT_FreeArena(cert->arena, PR_FALSE); - } - } - return; -} - -int -CERT_GetDBContentVersion(CERTCertDBHandle *handle) -{ - /* should read the DB content version from the pkcs #11 device */ - return 0; -} - -SECStatus -certdb_SaveSingleProfile(CERTCertificate *cert, const char *emailAddr, - SECItem *emailProfile, SECItem *profileTime) -{ - int64 oldtime; - int64 newtime; - SECStatus rv = SECFailure; - PRBool saveit; - SECItem oldprof, oldproftime; - SECItem *oldProfile = NULL; - SECItem *oldProfileTime = NULL; - PK11SlotInfo *slot = NULL; - NSSCertificate *c; - NSSCryptoContext *cc; - nssSMIMEProfile *stanProfile = NULL; - PRBool freeOldProfile = PR_FALSE; - - c = STAN_GetNSSCertificate(cert); - if (!c) return SECFailure; - cc = c->object.cryptoContext; - if (cc != NULL) { - stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c); - if (stanProfile) { - PORT_Assert(stanProfile->profileData); - SECITEM_FROM_NSSITEM(&oldprof, stanProfile->profileData); - oldProfile = &oldprof; - SECITEM_FROM_NSSITEM(&oldproftime, stanProfile->profileTime); - oldProfileTime = &oldproftime; - } - } else { - oldProfile = PK11_FindSMimeProfile(&slot, (char *)emailAddr, - &cert->derSubject, &oldProfileTime); - freeOldProfile = PR_TRUE; - } - - saveit = PR_FALSE; - - /* both profileTime and emailProfile have to exist or not exist */ - if ( emailProfile == NULL ) { - profileTime = NULL; - } else if ( profileTime == NULL ) { - emailProfile = NULL; - } - - if ( oldProfileTime == NULL ) { - saveit = PR_TRUE; - } else { - /* there was already a profile for this email addr */ - if ( profileTime ) { - /* we have an old and new profile - save whichever is more recent*/ - if ( oldProfileTime->len == 0 ) { - /* always replace if old entry doesn't have a time */ - oldtime = LL_MININT; - } else { - rv = DER_UTCTimeToTime(&oldtime, oldProfileTime); - if ( rv != SECSuccess ) { - goto loser; - } - } - - rv = DER_UTCTimeToTime(&newtime, profileTime); - if ( rv != SECSuccess ) { - goto loser; - } - - if ( LL_CMP(newtime, >, oldtime ) ) { - /* this is a newer profile, save it and cert */ - saveit = PR_TRUE; - } - } else { - saveit = PR_TRUE; - } - } - - - if (saveit) { - if (cc) { - if (stanProfile) { - /* stanProfile is already stored in the crypto context, - * overwrite the data - */ - NSSArena *arena = stanProfile->object.arena; - stanProfile->profileTime = nssItem_Create(arena, - NULL, - profileTime->len, - profileTime->data); - stanProfile->profileData = nssItem_Create(arena, - NULL, - emailProfile->len, - emailProfile->data); - } else if (profileTime && emailProfile) { - PRStatus nssrv; - NSSItem profTime, profData; - NSSITEM_FROM_SECITEM(&profTime, profileTime); - NSSITEM_FROM_SECITEM(&profData, emailProfile); - stanProfile = nssSMIMEProfile_Create(c, &profTime, &profData); - if (!stanProfile) goto loser; - nssrv = nssCryptoContext_ImportSMIMEProfile(cc, stanProfile); - rv = (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; - } - } else { - rv = PK11_SaveSMimeProfile(slot, (char *)emailAddr, - &cert->derSubject, emailProfile, profileTime); - } - } else { - rv = SECSuccess; - } - -loser: - if (oldProfile && freeOldProfile) { - SECITEM_FreeItem(oldProfile,PR_TRUE); - } - if (oldProfileTime && freeOldProfile) { - SECITEM_FreeItem(oldProfileTime,PR_TRUE); - } - if (stanProfile) { - nssSMIMEProfile_Destroy(stanProfile); - } - if (slot) { - PK11_FreeSlot(slot); - } - - return(rv); -} - -/* - * - * Manage S/MIME profiles - * - */ - -SECStatus -CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile, - SECItem *profileTime) -{ - const char *emailAddr; - SECStatus rv; - - if (!cert) { - return SECFailure; - } - - if (cert->slot && !PK11_IsInternal(cert->slot)) { - /* this cert comes from an external source, we need to add it - to the cert db before creating an S/MIME profile */ - PK11SlotInfo* internalslot = PK11_GetInternalKeySlot(); - if (!internalslot) { - return SECFailure; - } - rv = PK11_ImportCert(internalslot, cert, - CK_INVALID_HANDLE, NULL, PR_FALSE); - - PK11_FreeSlot(internalslot); - if (rv != SECSuccess ) { - return SECFailure; - } - } - - if (cert->slot && cert->isperm && CERT_IsUserCert(cert) && - (!emailProfile || !emailProfile->len)) { - /* Don't clobber emailProfile for user certs. */ - return SECSuccess; - } - - for (emailAddr = CERT_GetFirstEmailAddress(cert); emailAddr != NULL; - emailAddr = CERT_GetNextEmailAddress(cert,emailAddr)) { - rv = certdb_SaveSingleProfile(cert,emailAddr,emailProfile,profileTime); - if (rv != SECSuccess) { - return SECFailure; - } - } - return SECSuccess; - -} - - -SECItem * -CERT_FindSMimeProfile(CERTCertificate *cert) -{ - PK11SlotInfo *slot = NULL; - NSSCertificate *c; - NSSCryptoContext *cc; - SECItem *rvItem = NULL; - - if (!cert || !cert->emailAddr || !cert->emailAddr[0]) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - c = STAN_GetNSSCertificate(cert); - if (!c) return NULL; - cc = c->object.cryptoContext; - if (cc != NULL) { - nssSMIMEProfile *stanProfile; - stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c); - if (stanProfile) { - rvItem = SECITEM_AllocItem(NULL, NULL, - stanProfile->profileData->size); - if (rvItem) { - rvItem->data = stanProfile->profileData->data; - } - nssSMIMEProfile_Destroy(stanProfile); - } - return rvItem; - } - rvItem = - PK11_FindSMimeProfile(&slot, cert->emailAddr, &cert->derSubject, NULL); - if (slot) { - PK11_FreeSlot(slot); - } - return rvItem; -} - -/* - * deprecated functions that are now just stubs. - */ -/* - * Close the database - */ -void -__CERT_ClosePermCertDB(CERTCertDBHandle *handle) -{ - PORT_Assert("CERT_ClosePermCertDB is Deprecated" == NULL); - return; -} - -SECStatus -CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname, - PRBool readOnly) -{ - PORT_Assert("CERT_OpenCertDBFilename is Deprecated" == NULL); - PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); - return SECFailure; -} - -SECItem * -SECKEY_HashPassword(char *pw, SECItem *salt) -{ - PORT_Assert("SECKEY_HashPassword is Deprecated" == NULL); - PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); - return NULL; -} - -SECStatus -__CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle, - SECItem *derSubject, - void *cb, void *cbarg) -{ - PORT_Assert("CERT_TraversePermCertsForSubject is Deprecated" == NULL); - PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); - return SECFailure; -} - - -SECStatus -__CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname, - void *cb, void *cbarg) -{ - PORT_Assert("CERT_TraversePermCertsForNickname is Deprecated" == NULL); - PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); - return SECFailure; -} - - - diff --git a/security/nss/lib/certdb/xauthkid.c b/security/nss/lib/certdb/xauthkid.c deleted file mode 100644 index 462d22349..000000000 --- a/security/nss/lib/certdb/xauthkid.c +++ /dev/null @@ -1,128 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * X.509 v3 Subject Key Usage Extension - * - */ - -#include "prtypes.h" -#include "seccomon.h" -#include "secdert.h" -#include "secoidt.h" -#include "secasn1t.h" -#include "secasn1.h" -#include "secport.h" -#include "certt.h" -#include "genname.h" -#include "secerr.h" - -SEC_ASN1_MKSUB(SEC_IntegerTemplate) -SEC_ASN1_MKSUB(SEC_OctetStringTemplate) - -const SEC_ASN1Template CERTAuthKeyIDTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTAuthKeyID) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, - offsetof(CERTAuthKeyID,keyID), SEC_ASN1_SUB(SEC_OctetStringTemplate)}, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, - offsetof(CERTAuthKeyID, DERAuthCertIssuer), CERT_GeneralNamesTemplate}, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2, - offsetof(CERTAuthKeyID,authCertSerialNumber), - SEC_ASN1_SUB(SEC_IntegerTemplate) }, - { 0 } -}; - - - -SECStatus CERT_EncodeAuthKeyID (PRArenaPool *arena, CERTAuthKeyID *value, SECItem *encodedValue) -{ - SECStatus rv = SECFailure; - - PORT_Assert (value); - PORT_Assert (arena); - PORT_Assert (value->DERAuthCertIssuer == NULL); - PORT_Assert (encodedValue); - - do { - - /* If both of the authCertIssuer and the serial number exist, encode - the name first. Otherwise, it is an error if one exist and the other - is not. - */ - if (value->authCertIssuer) { - if (!value->authCertSerialNumber.data) { - PORT_SetError (SEC_ERROR_EXTENSION_VALUE_INVALID); - break; - } - - value->DERAuthCertIssuer = cert_EncodeGeneralNames - (arena, value->authCertIssuer); - if (!value->DERAuthCertIssuer) { - PORT_SetError (SEC_ERROR_EXTENSION_VALUE_INVALID); - break; - } - } - else if (value->authCertSerialNumber.data) { - PORT_SetError (SEC_ERROR_EXTENSION_VALUE_INVALID); - break; - } - - if (SEC_ASN1EncodeItem (arena, encodedValue, value, - CERTAuthKeyIDTemplate) == NULL) - break; - rv = SECSuccess; - - } while (0); - return(rv); -} - -CERTAuthKeyID * -CERT_DecodeAuthKeyID (PRArenaPool *arena, SECItem *encodedValue) -{ - CERTAuthKeyID * value = NULL; - SECStatus rv = SECFailure; - void * mark; - SECItem newEncodedValue; - - PORT_Assert (arena); - - do { - mark = PORT_ArenaMark (arena); - value = (CERTAuthKeyID*)PORT_ArenaZAlloc (arena, sizeof (*value)); - if (value == NULL) - break; - value->DERAuthCertIssuer = NULL; - /* 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, &newEncodedValue, encodedValue); - if ( rv != SECSuccess ) { - break; - } - - rv = SEC_QuickDERDecodeItem - (arena, value, CERTAuthKeyIDTemplate, &newEncodedValue); - if (rv != SECSuccess) - break; - - value->authCertIssuer = cert_DecodeGeneralNames (arena, value->DERAuthCertIssuer); - if (value->authCertIssuer == NULL) - break; - - /* what if the general name contains other format but not URI ? - hl - */ - if ((value->authCertSerialNumber.data && !value->authCertIssuer) || - (!value->authCertSerialNumber.data && value->authCertIssuer)){ - PORT_SetError (SEC_ERROR_EXTENSION_VALUE_INVALID); - break; - } - } while (0); - - if (rv != SECSuccess) { - PORT_ArenaRelease (arena, mark); - return ((CERTAuthKeyID *)NULL); - } - PORT_ArenaUnmark(arena, mark); - return (value); -} diff --git a/security/nss/lib/certdb/xbsconst.c b/security/nss/lib/certdb/xbsconst.c deleted file mode 100644 index 41bf3c537..000000000 --- a/security/nss/lib/certdb/xbsconst.c +++ /dev/null @@ -1,145 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * X.509 v3 Basic Constraints Extension - */ - -#include "prtypes.h" -#include <limits.h> /* for LONG_MAX */ -#include "seccomon.h" -#include "secdert.h" -#include "secoidt.h" -#include "secasn1t.h" -#include "secasn1.h" -#include "certt.h" -#include "secder.h" -#include "prprf.h" -#include "secerr.h" - -typedef struct EncodedContext{ - SECItem isCA; - SECItem pathLenConstraint; - SECItem encodedValue; - PRArenaPool *arena; -}EncodedContext; - -static const SEC_ASN1Template CERTBasicConstraintsTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(EncodedContext) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */ - offsetof(EncodedContext,isCA)}, - { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER, - offsetof(EncodedContext,pathLenConstraint) }, - { 0, } -}; - -static unsigned char hexTrue = 0xff; -static unsigned char hexFalse = 0x00; - -#define GEN_BREAK(status) rv = status; break; - -SECStatus CERT_EncodeBasicConstraintValue - (PRArenaPool *arena, CERTBasicConstraints *value, SECItem *encodedValue) -{ - EncodedContext encodeContext; - PRArenaPool *our_pool = NULL; - SECStatus rv = SECSuccess; - - do { - PORT_Memset (&encodeContext, 0, sizeof (encodeContext)); - if (!value->isCA && value->pathLenConstraint >= 0) { - PORT_SetError (SEC_ERROR_EXTENSION_VALUE_INVALID); - GEN_BREAK (SECFailure); - } - - encodeContext.arena = arena; - if (value->isCA == PR_TRUE) { - encodeContext.isCA.data = &hexTrue ; - encodeContext.isCA.len = 1; - } - - /* If the pathLenConstraint is less than 0, then it should be - * omitted from the encoding. - */ - if (value->isCA && value->pathLenConstraint >= 0) { - our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); - if (our_pool == NULL) { - PORT_SetError (SEC_ERROR_NO_MEMORY); - GEN_BREAK (SECFailure); - } - if (SEC_ASN1EncodeUnsignedInteger - (our_pool, &encodeContext.pathLenConstraint, - (unsigned long)value->pathLenConstraint) == NULL) { - PORT_SetError (SEC_ERROR_NO_MEMORY); - GEN_BREAK (SECFailure); - } - } - if (SEC_ASN1EncodeItem (arena, encodedValue, &encodeContext, - CERTBasicConstraintsTemplate) == NULL) { - GEN_BREAK (SECFailure); - } - } while (0); - if (our_pool) - PORT_FreeArena (our_pool, PR_FALSE); - return(rv); - -} - -SECStatus CERT_DecodeBasicConstraintValue - (CERTBasicConstraints *value, SECItem *encodedValue) -{ - EncodedContext decodeContext; - PRArenaPool *our_pool; - SECStatus rv = SECSuccess; - - do { - PORT_Memset (&decodeContext, 0, sizeof (decodeContext)); - /* initialize the value just in case we got "0x30 00", or when the - pathLenConstraint is omitted. - */ - decodeContext.isCA.data =&hexFalse; - decodeContext.isCA.len = 1; - - our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); - if (our_pool == NULL) { - PORT_SetError (SEC_ERROR_NO_MEMORY); - GEN_BREAK (SECFailure); - } - - rv = SEC_QuickDERDecodeItem - (our_pool, &decodeContext, CERTBasicConstraintsTemplate, encodedValue); - if (rv == SECFailure) - break; - - value->isCA = decodeContext.isCA.data - ? (PRBool)(decodeContext.isCA.data[0] != 0) - : PR_FALSE; - if (decodeContext.pathLenConstraint.data == NULL) { - /* if the pathLenConstraint is not encoded, and the current setting - is CA, then the pathLenConstraint should be set to a negative number - for unlimited certificate path. - */ - if (value->isCA) - value->pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT; - } else if (value->isCA) { - long len = DER_GetInteger (&decodeContext.pathLenConstraint); - if (len < 0 || len == LONG_MAX) { - PORT_SetError (SEC_ERROR_BAD_DER); - GEN_BREAK (SECFailure); - } - value->pathLenConstraint = len; - } else { - /* here we get an error where the subject is not a CA, but - the pathLenConstraint is set */ - PORT_SetError (SEC_ERROR_BAD_DER); - GEN_BREAK (SECFailure); - break; - } - - } while (0); - PORT_FreeArena (our_pool, PR_FALSE); - return (rv); - -} diff --git a/security/nss/lib/certdb/xconst.c b/security/nss/lib/certdb/xconst.c deleted file mode 100644 index 327b7ddc4..000000000 --- a/security/nss/lib/certdb/xconst.c +++ /dev/null @@ -1,286 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * X.509 Extension Encoding - */ - -#include "prtypes.h" -#include "seccomon.h" -#include "secdert.h" -#include "secoidt.h" -#include "secasn1t.h" -#include "secasn1.h" -#include "cert.h" -#include "secder.h" -#include "prprf.h" -#include "xconst.h" -#include "genname.h" -#include "secasn1.h" -#include "secerr.h" - - -static const SEC_ASN1Template CERTSubjectKeyIDTemplate[] = { - { SEC_ASN1_OCTET_STRING } -}; - - -static const SEC_ASN1Template CERTIA5TypeTemplate[] = { - { SEC_ASN1_IA5_STRING } -}; - -SEC_ASN1_MKSUB(SEC_GeneralizedTimeTemplate) - -static const SEC_ASN1Template CERTPrivateKeyUsagePeriodTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTPrivKeyUsagePeriod) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, - offsetof(CERTPrivKeyUsagePeriod, notBefore), - SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, - offsetof(CERTPrivKeyUsagePeriod, notAfter), - SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate)}, - { 0, } -}; - - -const SEC_ASN1Template CERTAltNameTemplate[] = { - { SEC_ASN1_CONSTRUCTED, offsetof(CERTAltNameEncodedContext, encodedGenName), - CERT_GeneralNamesTemplate} -}; - -const SEC_ASN1Template CERTAuthInfoAccessItemTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CERTAuthInfoAccess) }, - { SEC_ASN1_OBJECT_ID, - offsetof(CERTAuthInfoAccess, method) }, - { SEC_ASN1_ANY, - offsetof(CERTAuthInfoAccess, derLocation) }, - { 0, } -}; - -const SEC_ASN1Template CERTAuthInfoAccessTemplate[] = { - { SEC_ASN1_SEQUENCE_OF, 0, CERTAuthInfoAccessItemTemplate } -}; - - -SECStatus -CERT_EncodeSubjectKeyID(PRArenaPool *arena, const SECItem* srcString, - SECItem *encodedValue) -{ - SECStatus rv = SECSuccess; - - if (!srcString) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - if (SEC_ASN1EncodeItem (arena, encodedValue, srcString, - CERTSubjectKeyIDTemplate) == NULL) { - rv = SECFailure; - } - - return(rv); -} - - -SECStatus -CERT_EncodePrivateKeyUsagePeriod(PRArenaPool *arena, - CERTPrivKeyUsagePeriod *pkup, - SECItem *encodedValue) -{ - SECStatus rv = SECSuccess; - - if (SEC_ASN1EncodeItem (arena, encodedValue, pkup, - CERTPrivateKeyUsagePeriodTemplate) == NULL) { - rv = SECFailure; - } - return(rv); -} - -CERTPrivKeyUsagePeriod * -CERT_DecodePrivKeyUsagePeriodExtension(PLArenaPool *arena, SECItem *extnValue) -{ - SECStatus rv; - CERTPrivKeyUsagePeriod *pPeriod; - SECItem newExtnValue; - - /* allocate the certificate policies structure */ - pPeriod = PORT_ArenaZNew(arena, CERTPrivKeyUsagePeriod); - if ( pPeriod == NULL ) { - goto loser; - } - - pPeriod->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; - } - - rv = SEC_QuickDERDecodeItem(arena, pPeriod, - CERTPrivateKeyUsagePeriodTemplate, - &newExtnValue); - if ( rv != SECSuccess ) { - goto loser; - } - return pPeriod; - -loser: - return NULL; -} - - -SECStatus -CERT_EncodeIA5TypeExtension(PRArenaPool *arena, char *value, SECItem *encodedValue) -{ - SECItem encodeContext; - SECStatus rv = SECSuccess; - - - PORT_Memset (&encodeContext, 0, sizeof (encodeContext)); - - if (value != NULL) { - encodeContext.data = (unsigned char *)value; - encodeContext.len = strlen(value); - } - if (SEC_ASN1EncodeItem (arena, encodedValue, &encodeContext, - CERTIA5TypeTemplate) == NULL) { - rv = SECFailure; - } - - return(rv); -} - -SECStatus -CERT_EncodeAltNameExtension(PRArenaPool *arena, CERTGeneralName *value, SECItem *encodedValue) -{ - SECItem **encodedGenName; - SECStatus rv = SECSuccess; - - encodedGenName = cert_EncodeGeneralNames(arena, value); - if (SEC_ASN1EncodeItem (arena, encodedValue, &encodedGenName, - CERT_GeneralNamesTemplate) == NULL) { - rv = SECFailure; - } - - return rv; -} - -CERTGeneralName * -CERT_DecodeAltNameExtension(PRArenaPool *reqArena, SECItem *EncodedAltName) -{ - SECStatus rv = SECSuccess; - CERTAltNameEncodedContext encodedContext; - SECItem* newEncodedAltName; - - if (!reqArena) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - - newEncodedAltName = SECITEM_ArenaDupItem(reqArena, EncodedAltName); - if (!newEncodedAltName) { - return NULL; - } - - encodedContext.encodedGenName = NULL; - PORT_Memset(&encodedContext, 0, sizeof(CERTAltNameEncodedContext)); - rv = SEC_QuickDERDecodeItem (reqArena, &encodedContext, - CERT_GeneralNamesTemplate, newEncodedAltName); - if (rv == SECFailure) { - goto loser; - } - if (encodedContext.encodedGenName && encodedContext.encodedGenName[0]) - return cert_DecodeGeneralNames(reqArena, - encodedContext.encodedGenName); - /* Extension contained an empty GeneralNames sequence */ - /* Treat as extension not found */ - PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND); -loser: - return NULL; -} - - -SECStatus -CERT_EncodeNameConstraintsExtension(PRArenaPool *arena, - CERTNameConstraints *value, - SECItem *encodedValue) -{ - SECStatus rv = SECSuccess; - - rv = cert_EncodeNameConstraints(value, arena, encodedValue); - return rv; -} - - -CERTNameConstraints * -CERT_DecodeNameConstraintsExtension(PRArenaPool *arena, - SECItem *encodedConstraints) -{ - return cert_DecodeNameConstraints(arena, encodedConstraints); -} - - -CERTAuthInfoAccess ** -CERT_DecodeAuthInfoAccessExtension(PRArenaPool *reqArena, - SECItem *encodedExtension) -{ - CERTAuthInfoAccess **info = NULL; - SECStatus rv; - int i; - SECItem* newEncodedExtension; - - if (!reqArena) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; - } - - newEncodedExtension = SECITEM_ArenaDupItem(reqArena, encodedExtension); - if (!newEncodedExtension) { - return NULL; - } - - rv = SEC_QuickDERDecodeItem(reqArena, &info, CERTAuthInfoAccessTemplate, - newEncodedExtension); - if (rv != SECSuccess || info == NULL) { - return NULL; - } - - for (i = 0; info[i] != NULL; i++) { - info[i]->location = CERT_DecodeGeneralName(reqArena, - &(info[i]->derLocation), - NULL); - } - return info; -} - -SECStatus -CERT_EncodeInfoAccessExtension(PRArenaPool *arena, - CERTAuthInfoAccess **info, - SECItem *dest) -{ - SECItem *dummy; - int i; - - PORT_Assert(info != NULL); - PORT_Assert(dest != NULL); - if (info == NULL || dest == NULL) { - return SECFailure; - } - - for (i = 0; info[i] != NULL; i++) { - if (CERT_EncodeGeneralName(info[i]->location, &(info[i]->derLocation), - arena) == NULL) - /* Note that this may leave some of the locations filled in. */ - return SECFailure; - } - dummy = SEC_ASN1EncodeItem(arena, dest, &info, - CERTAuthInfoAccessTemplate); - if (dummy == NULL) { - return SECFailure; - } - return SECSuccess; -} diff --git a/security/nss/lib/certdb/xconst.h b/security/nss/lib/certdb/xconst.h deleted file mode 100644 index 14eb75c98..000000000 --- a/security/nss/lib/certdb/xconst.h +++ /dev/null @@ -1,36 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.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 _XCONST_H_ -#define _XCONST_H_ - -#include "certt.h" - -typedef struct CERTAltNameEncodedContextStr { - SECItem **encodedGenName; -} CERTAltNameEncodedContext; - - - -SEC_BEGIN_PROTOS - -extern SECStatus -CERT_EncodePrivateKeyUsagePeriod(PRArenaPool *arena, - CERTPrivKeyUsagePeriod *pkup, - SECItem *encodedValue); - -extern SECStatus -CERT_EncodeNameConstraintsExtension(PRArenaPool *arena, - CERTNameConstraints *value, - SECItem *encodedValue); - -extern SECStatus -CERT_EncodeIA5TypeExtension(PRArenaPool *arena, char *value, - SECItem *encodedValue); - -SECStatus -cert_EncodeAuthInfoAccessExtension(PRArenaPool *arena, - CERTAuthInfoAccess **info, - SECItem *dest); -SEC_END_PROTOS -#endif |