summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/certdb/polcyxtn.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /security/nss/lib/certdb/polcyxtn.c
parentInitial commit. (diff)
downloadfirefox-esr-upstream.tar.xz
firefox-esr-upstream.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--security/nss/lib/certdb/polcyxtn.c806
1 files changed, 806 insertions, 0 deletions
diff --git a/security/nss/lib/certdb/polcyxtn.c b/security/nss/lib/certdb/polcyxtn.c
new file mode 100644
index 0000000000..aae34e2433
--- /dev/null
+++ b/security/nss/lib/certdb/polcyxtn.c
@@ -0,0 +1,806 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Support for various policy related extensions
+ */
+
+#include "seccomon.h"
+#include "secport.h"
+#include "secder.h"
+#include "cert.h"
+#include "secoid.h"
+#include "secasn1.h"
+#include "secerr.h"
+#include "nspr.h"
+
+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(const SECItem *extnValue)
+{
+ PLArenaPool *arena = NULL;
+ SECStatus rv;
+ CERTCertificatePolicies *policies;
+ CERTPolicyInfo **policyInfos, *policyInfo;
+ CERTPolicyQualifier **policyQualifiers, *policyQualifier;
+ SECItem newExtnValue;
+
+ /* make a new arena */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!arena) {
+ goto loser;
+ }
+
+ /* allocate the 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)
+{
+ PLArenaPool *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, const SECItem *encodedValue)
+{
+ CERTCertificatePolicyConstraints decodeContext;
+ PLArenaPool *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;
+ PLArenaPool *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)
+{
+ PLArenaPool *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(const SECItem *seqItem)
+{
+ PLArenaPool *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:
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ 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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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);
+}