/************************************************************************* * * C h k F i p s M o d e * If arg=="true", verify FIPS mode is enabled on the internal module. * If arg=="false", verify FIPS mode is disabled on the internal module. */ Error ChkFipsMode(char *arg) { if (!PORT_Strcasecmp(arg, "true")) { if (PK11_IsFIPS()) { PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]); } else { PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]); return FIPS_SWITCH_FAILED_ERR; } } else if (!PORT_Strcasecmp(arg, "false")) { if (!PK11_IsFIPS()) { PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]); } else { PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]); return FIPS_SWITCH_FAILED_ERR; } } else { PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]); return INVALID_FIPS_ARG; } return SUCCESS; }
/* parse a single slot specific parameter */ static void nssutil_argDecodeSingleSlotInfo(char *name, char *params, struct NSSUTILPreSlotInfoStr *slotInfo) { char *askpw; slotInfo->slotID = NSSUTIL_ArgDecodeNumber(name); slotInfo->defaultFlags = NSSUTIL_ArgParseSlotFlags("slotFlags", params); slotInfo->timeout = NSSUTIL_ArgReadLong("timeout", params, 0, NULL); askpw = NSSUTIL_ArgGetParamValue("askpw", params); slotInfo->askpw = 0; if (askpw) { if (PORT_Strcasecmp(askpw, "every") == 0) { slotInfo->askpw = -1; } else if (PORT_Strcasecmp(askpw, "timeout") == 0) { slotInfo->askpw = 1; } PORT_Free(askpw); slotInfo->defaultFlags |= PK11_OWN_PW_DEFAULTS; } slotInfo->hasRootCerts = NSSUTIL_ArgHasFlag("rootFlags", "hasRootCerts", params); slotInfo->hasRootTrust = NSSUTIL_ArgHasFlag("rootFlags", "hasRootTrust", params); }
/************************************************************************* * * F i p s M o d e * If arg=="true", enable FIPS mode on the internal module. If arg=="false", * disable FIPS mode on the internal module. */ Error FipsMode(char *arg) { char *internal_name; if (!PORT_Strcasecmp(arg, "true")) { if (!PK11_IsFIPS()) { internal_name = PR_smprintf("%s", SECMOD_GetInternalModule()->commonName); if (SECMOD_DeleteInternalModule(internal_name) != SECSuccess) { PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError())); PR_smprintf_free(internal_name); PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]); return FIPS_SWITCH_FAILED_ERR; } PR_smprintf_free(internal_name); if (!PK11_IsFIPS()) { PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]); return FIPS_SWITCH_FAILED_ERR; } PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]); } else { PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_ON_ERR]); return FIPS_ALREADY_ON_ERR; } } else if (!PORT_Strcasecmp(arg, "false")) { if (PK11_IsFIPS()) { internal_name = PR_smprintf("%s", SECMOD_GetInternalModule()->commonName); if (SECMOD_DeleteInternalModule(internal_name) != SECSuccess) { PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError())); PR_smprintf_free(internal_name); PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]); return FIPS_SWITCH_FAILED_ERR; } PR_smprintf_free(internal_name); if (PK11_IsFIPS()) { PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]); return FIPS_SWITCH_FAILED_ERR; } PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]); } else { PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_OFF_ERR]); return FIPS_ALREADY_OFF_ERR; } } else { PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]); return INVALID_FIPS_ARG; } return SUCCESS; }
/* turn the slot flags into a bit mask */ unsigned long NSSUTIL_ArgParseSlotFlags(const char *label, const char *params) { char *flags; const char *index; unsigned long retValue = 0; int i; PRBool all = PR_FALSE; flags = NSSUTIL_ArgGetParamValue(label, params); if (flags == NULL) return 0; if (PORT_Strcasecmp(flags, "all") == 0) all = PR_TRUE; for (index = flags; *index; index = NSSUTIL_ArgNextFlag(index)) { for (i = 0; i < nssutil_argSlotFlagTableSize; i++) { if (all || (PORT_Strncasecmp(index, nssutil_argSlotFlagTable[i].name, nssutil_argSlotFlagTable[i].len) == 0)) { retValue |= nssutil_argSlotFlagTable[i].value; } } } PORT_Free(flags); return retValue; }
static SECOidData * HashNameToOID(const char *hashName) { HASH_HashType htype; SECOidData *hashOID; for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) { hashOID = HashTypeToOID(htype); if (PORT_Strcasecmp(hashName, hashOID->desc) == 0) break; } if (htype == HASH_AlgTOTAL) return NULL; return hashOID; }
/************************************************************************ * * g e t F l a g s F r o m S t r i n g * * Parses a mechanism list passed on the command line and converts it * to an unsigned long bitmask. * string is a colon-separated string of constants * array is an array of MaskStrings. * elements is the number of elements in array. */ static unsigned long getFlagsFromString(char *string, const MaskString array[], int elements) { unsigned long ret = 0; short i = 0; char *cp; char *buf; char *end; if (!string || !string[0]) { return ret; } /* Make a temporary copy of the string */ buf = PR_Malloc(strlen(string) + 1); if (!buf) { out_of_memory(); } strcpy(buf, string); /* Look at each element of the list passed in */ for (cp = buf; cp && *cp; cp = (end ? end + 1 : NULL)) { /* Look at the string up to the next colon */ end = strchr(cp, ':'); if (end) { *end = '\0'; } /* Find which element this is */ for (i = 0; i < elements; i++) { if (!PORT_Strcasecmp(cp, array[i].name)) { break; } } if (i == elements) { /* Skip a bogus string, but print a warning message */ PR_fprintf(PR_STDERR, errStrings[INVALID_CONSTANT_ERR], cp); continue; } ret |= array[i].mask; } PR_Free(buf); return ret; }
int JAR_get_metainfo(JAR *jar, char *name, char *header, void **info, unsigned long *length) { JAR_Item *it; ZZLink *link; ZZList *list; PORT_Assert(jar != NULL && header != NULL); if (jar == NULL || header == NULL) return JAR_ERR_PNF; list = jar->metainfo; if (ZZ_ListEmpty(list)) return JAR_ERR_PNF; for (link = ZZ_ListHead(list); !ZZ_ListIterDone(list, link); link = link->next) { it = link->thing; if (it->type == jarTypeMeta) { JAR_Metainfo *met; if ((name && !it->pathname) || (!name && it->pathname)) continue; if (name && it->pathname && strcmp(it->pathname, name)) continue; met = (JAR_Metainfo *)it->data; if (!PORT_Strcasecmp(met->header, header)) { *info = PORT_Strdup(met->info); *length = PORT_Strlen(met->info); return 0; } } } return JAR_ERR_PNF; }
/*************************************************************************** * * v e r i f y _ g l o b a l */ static int verify_global(JAR *jar) { FILE *fp; JAR_Context *ctx; JAR_Item *it; JAR_Digest *globaldig; char *ext; unsigned char *md5_digest, *sha1_digest; unsigned int sha1_length, md5_length; int retval = 0; char buf[BUFSIZ]; ctx = JAR_find(jar, "*", jarTypePhy); while (JAR_find_next(ctx, &it) >= 0) { if (!PORT_Strncmp(it->pathname, "META-INF", 8)) { for (ext = it->pathname; *ext; ext++) ; while (ext > it->pathname && *ext != '.') ext--; if (verbosity >= 0) { if (!PORT_Strcasecmp(ext, ".rsa")) { PR_fprintf(outputFD, "found a RSA signature file: %s\n", it->pathname); } if (!PORT_Strcasecmp(ext, ".dsa")) { PR_fprintf(outputFD, "found a DSA signature file: %s\n", it->pathname); } if (!PORT_Strcasecmp(ext, ".mf")) { PR_fprintf(outputFD, "found a MF master manifest file: %s\n", it->pathname); } } if (!PORT_Strcasecmp(ext, ".sf")) { if (verbosity >= 0) { PR_fprintf(outputFD, "found a SF signature manifest file: %s\n", it->pathname); } rm_dash_r(TMP_OUTPUT); if (JAR_extract(jar, it->pathname, TMP_OUTPUT) < 0) { PR_fprintf(errorFD, "%s: error extracting %s\n", PROGRAM_NAME, it->pathname); errorCount++; retval = -1; continue; } md5_digest = NULL; sha1_digest = NULL; if ((fp = fopen(TMP_OUTPUT, "rb")) != NULL) { while (fgets(buf, BUFSIZ, fp)) { char *s; if (*buf == 0 || *buf == '\n' || *buf == '\r') break; for (s = buf; *s && *s != '\n' && *s != '\r'; s++) ; *s = 0; if (!PORT_Strncmp(buf, "MD5-Digest: ", 12)) { md5_digest = ATOB_AsciiToData(buf + 12, &md5_length); } if (!PORT_Strncmp(buf, "SHA1-Digest: ", 13)) { sha1_digest = ATOB_AsciiToData(buf + 13, &sha1_length); } if (!PORT_Strncmp(buf, "SHA-Digest: ", 12)) { sha1_digest = ATOB_AsciiToData(buf + 12, &sha1_length); } } globaldig = jar->globalmeta; if (globaldig && md5_digest && verbosity >= 0) { PR_fprintf(outputFD, " md5 digest on global metainfo: %s\n", PORT_Memcmp(md5_digest, globaldig->md5, MD5_LENGTH) ? "no match" : "match"); } if (globaldig && sha1_digest && verbosity >= 0) { PR_fprintf(outputFD, " sha digest on global metainfo: %s\n", PORT_Memcmp(sha1_digest, globaldig->sha1, SHA1_LENGTH) ? "no match" : "match"); } if (globaldig == NULL && verbosity >= 0) { PR_fprintf(outputFD, "global metadigest is not available, strange.\n"); } PORT_Free(md5_digest); PORT_Free(sha1_digest); fclose(fp); } } } } JAR_find_end(ctx); return retval; }
/* 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, char **pbp, char *endptr) { CERTAVA *a; const NameToKind *n2k; 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; }
/* * FUNCTION: pkix_pl_OcspResponse_Create * DESCRIPTION: * * This function transmits the OcspRequest pointed to by "request" and obtains * an OcspResponse, which it stores at "pOcspResponse". If the HTTPClient * supports non-blocking I/O this function may store a non-NULL value at * "pNBIOContext" (the WOULDBLOCK condition). In that case the caller should * make a subsequent call with the same value in "pNBIOContext" and * "pOcspResponse" to resume the operation. Additional WOULDBLOCK returns may * occur; the caller should persist until a return occurs with NULL stored at * "pNBIOContext". * * If a SEC_HttpClientFcn "responder" is supplied, it is used as the client * to which the OCSP query is sent. If none is supplied, the default responder * is used. * * If an OcspResponse_VerifyCallback "verifyFcn" is supplied, it is used to * verify the Cert received from the responder as the signer. If none is * supplied, the default verification function is used. * * The contents of "request" are ignored on calls subsequent to a WOULDBLOCK * return, and the caller is permitted to supply NULL. * * PARAMETERS * "request" * Address of the OcspRequest for which a response is desired. * "responder" * Address, if non-NULL, of the SEC_HttpClientFcn to be sent the OCSP * query. * "verifyFcn" * Address, if non-NULL, of the OcspResponse_VerifyCallback function to be * used to verify the Cert of the OCSP responder. * "pNBIOContext" * Address at which platform-dependent information is stored for handling * of non-blocking I/O. Must be non-NULL. * "pOcspResponse" * The address where the created OcspResponse is stored. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns an OcspResponse Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_OcspResponse_Create( PKIX_PL_OcspRequest *request, void *responder, PKIX_PL_VerifyCallback verifyFcn, void **pNBIOContext, PKIX_PL_OcspResponse **pResponse, void *plContext) { void *nbioContext = NULL; PKIX_PL_OcspResponse *ocspResponse = NULL; const SEC_HttpClientFcn *httpClient = NULL; const SEC_HttpClientFcnV1 *hcv1 = NULL; SECStatus rv = SECFailure; char *location = NULL; char *hostname = NULL; char *path = NULL; char *responseContentType = NULL; PRUint16 port = 0; SEC_HTTP_SERVER_SESSION serverSession = NULL; SEC_HTTP_REQUEST_SESSION sessionRequest = NULL; SECItem *encodedRequest = NULL; PRUint16 responseCode = 0; char *responseData = NULL; PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Create"); PKIX_NULLCHECK_TWO(pNBIOContext, pResponse); nbioContext = *pNBIOContext; *pNBIOContext = NULL; if (nbioContext != NULL) { ocspResponse = *pResponse; PKIX_NULLCHECK_ONE(ocspResponse); httpClient = ocspResponse->httpClient; serverSession = ocspResponse->serverSession; sessionRequest = ocspResponse->sessionRequest; PKIX_NULLCHECK_THREE(httpClient, serverSession, sessionRequest); } else { PKIX_UInt32 timeout = ((PKIX_PL_NssContext*)plContext)->timeoutSeconds; PKIX_NULLCHECK_ONE(request); PKIX_CHECK(pkix_pl_OcspRequest_GetEncoded (request, &encodedRequest, plContext), PKIX_OCSPREQUESTGETENCODEDFAILED); /* prepare initial message to HTTPClient */ /* Is there a default responder and is it enabled? */ if (responder) { httpClient = (const SEC_HttpClientFcn *)responder; } else { httpClient = SEC_GetRegisteredHttpClient(); } if (httpClient && (httpClient->version == 1)) { hcv1 = &(httpClient->fcnTable.ftable1); PKIX_CHECK(pkix_pl_OcspRequest_GetLocation (request, &location, plContext), PKIX_OCSPREQUESTGETLOCATIONFAILED); /* parse location -> hostname, port, path */ rv = CERT_ParseURL(location, &hostname, &port, &path); if (rv == SECFailure || hostname == NULL || path == NULL) { PKIX_ERROR(PKIX_URLPARSINGFAILED); } rv = (*hcv1->createSessionFcn)(hostname, port, &serverSession); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } rv = (*hcv1->createFcn)(serverSession, "http", path, "POST", PR_SecondsToInterval(timeout), &sessionRequest); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } rv = (*hcv1->setPostDataFcn)(sessionRequest, (char *)encodedRequest->data, encodedRequest->len, "application/ocsp-request"); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } /* create a PKIX_PL_OcspResponse object */ PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_OCSPRESPONSE_TYPE, sizeof (PKIX_PL_OcspResponse), (PKIX_PL_Object **)&ocspResponse, plContext), PKIX_COULDNOTCREATEOBJECT); PKIX_INCREF(request); ocspResponse->request = request; ocspResponse->httpClient = httpClient; ocspResponse->serverSession = serverSession; ocspResponse->sessionRequest = sessionRequest; ocspResponse->verifyFcn = verifyFcn; ocspResponse->handle = CERT_GetDefaultCertDB(); ocspResponse->encodedResponse = NULL; ocspResponse->arena = NULL; ocspResponse->producedAt = 0; ocspResponse->producedAtDate = NULL; ocspResponse->pkixSignerCert = NULL; ocspResponse->nssOCSPResponse = NULL; ocspResponse->signerCert = NULL; } } /* begin or resume IO to HTTPClient */ if (httpClient && (httpClient->version == 1)) { PRUint32 responseDataLen = ((PKIX_PL_NssContext*)plContext)->maxResponseLength; hcv1 = &(httpClient->fcnTable.ftable1); rv = (*hcv1->trySendAndReceiveFcn)(sessionRequest, (PRPollDesc **)&nbioContext, &responseCode, &responseContentType, NULL, /* responseHeaders */ (const char **)&responseData, &responseDataLen); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } /* responseContentType is a pointer to the null-terminated * string returned by httpclient. Memory allocated for context * type will be freed with freeing of the HttpClient struct. */ if (PORT_Strcasecmp(responseContentType, "application/ocsp-response")) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } if (nbioContext != NULL) { *pNBIOContext = nbioContext; goto cleanup; } if (responseCode != 200) { PKIX_ERROR(PKIX_OCSPBADHTTPRESPONSE); } ocspResponse->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (ocspResponse->arena == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } ocspResponse->encodedResponse = SECITEM_AllocItem (ocspResponse->arena, NULL, responseDataLen); if (ocspResponse->encodedResponse == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } PORT_Memcpy(ocspResponse->encodedResponse->data, responseData, responseDataLen); } *pResponse = ocspResponse; cleanup: if (path != NULL) { PORT_Free(path); } if (hostname != NULL) { PORT_Free(hostname); } if (PKIX_ERROR_RECEIVED){ if (ocspResponse) { PKIX_DECREF(ocspResponse); } else { if (serverSession) hcv1->freeSessionFcn(serverSession); if (sessionRequest) hcv1->freeFcn(sessionRequest); } } PKIX_RETURN(OCSPRESPONSE); }
/* * FUNCTION: pkix_pl_HttpCertStore_ProcessCrlResponse * DESCRIPTION: * * This function verifies that the response code pointed to by "responseCode" * and the content type pointed to by "responseContentType" are as expected, * and then decodes the data pointed to by "responseData", of length * "responseDataLen", into a List of Crls, possibly empty, which is returned * at "pCrlList". * * PARAMETERS: * "responseCode" * The value of the HTTP response code. * "responseContentType" * The address of the Content-type string. Must be non-NULL. * "responseData" * The address of the message data. Must be non-NULL. * "responseDataLen" * The length of the message data. * "pCrlList" * The address of the List that is created. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a HttpCertStore Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_HttpCertStore_ProcessCrlResponse( PRUint16 responseCode, const char *responseContentType, const char *responseData, PRUint32 responseDataLen, PKIX_List **pCrlList, void *plContext) { PRArenaPool *arena = NULL; SECItem *encodedResponse = NULL; PRInt16 compareVal = 0; PKIX_List *crls = NULL; PKIX_ENTER (HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStore_ProcessCrlResponse"); PKIX_NULLCHECK_ONE(pCrlList); if (responseCode != 200) { PKIX_ERROR(PKIX_BADHTTPRESPONSE); } /* check that response type is application/pkix-crl */ if (responseContentType == NULL) { PKIX_ERROR(PKIX_NOCONTENTTYPEINHTTPRESPONSE); } compareVal = PORT_Strcasecmp(responseContentType, "application/pkix-crl"); if (compareVal != 0) { PKIX_ERROR(PKIX_CONTENTTYPENOTPKIXCRL); } /* Make a SECItem of the response data */ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } if (responseData == NULL) { PKIX_ERROR(PKIX_NORESPONSEDATAINHTTPRESPONSE); } encodedResponse = SECITEM_AllocItem(arena, NULL, responseDataLen); if (encodedResponse == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } PORT_Memcpy(encodedResponse->data, responseData, responseDataLen); PKIX_CHECK(PKIX_List_Create(&crls, plContext), PKIX_LISTCREATEFAILED); PKIX_CHECK(pkix_pl_CRL_CreateToList (encodedResponse, crls, plContext), PKIX_CRLCREATETOLISTFAILED); *pCrlList = crls; cleanup: if (PKIX_ERROR_RECEIVED) { PKIX_DECREF(crls); } if (arena != NULL) { PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena, (arena, PR_FALSE)); } PKIX_RETURN(HTTPCERTSTORECONTEXT); }