michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * Support for various policy related extensions michael@0: */ michael@0: michael@0: #include "seccomon.h" michael@0: #include "secport.h" michael@0: #include "secder.h" michael@0: #include "cert.h" michael@0: #include "secoid.h" michael@0: #include "secasn1.h" michael@0: #include "secerr.h" michael@0: #include "nspr.h" michael@0: michael@0: SEC_ASN1_MKSUB(SEC_IntegerTemplate) michael@0: SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) michael@0: michael@0: const SEC_ASN1Template CERT_DisplayTextTypeTemplate[] = { michael@0: { SEC_ASN1_CHOICE, offsetof(SECItem, type), 0, sizeof(SECItem) }, michael@0: { SEC_ASN1_IA5_STRING, 0, 0, siAsciiString}, michael@0: { SEC_ASN1_VISIBLE_STRING , 0, 0, siVisibleString}, michael@0: { SEC_ASN1_BMP_STRING , 0, 0, siBMPString }, michael@0: { SEC_ASN1_UTF8_STRING , 0, 0, siUTF8String }, michael@0: { 0 } michael@0: }; michael@0: michael@0: const SEC_ASN1Template CERT_NoticeReferenceTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, michael@0: 0, NULL, sizeof(CERTNoticeReference) }, michael@0: { SEC_ASN1_INLINE, michael@0: offsetof(CERTNoticeReference, organization), michael@0: CERT_DisplayTextTypeTemplate, 0 }, michael@0: { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, michael@0: offsetof(CERTNoticeReference, noticeNumbers), michael@0: SEC_ASN1_SUB(SEC_IntegerTemplate) }, michael@0: { 0 } michael@0: }; michael@0: michael@0: const SEC_ASN1Template CERT_UserNoticeTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, michael@0: 0, NULL, sizeof(CERTUserNotice) }, michael@0: { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, michael@0: offsetof(CERTUserNotice, noticeReference), michael@0: CERT_NoticeReferenceTemplate, 0 }, michael@0: { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, michael@0: offsetof(CERTUserNotice, displayText), michael@0: CERT_DisplayTextTypeTemplate, 0 }, michael@0: { 0 } michael@0: }; michael@0: michael@0: const SEC_ASN1Template CERT_PolicyQualifierTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, michael@0: 0, NULL, sizeof(CERTPolicyQualifier) }, michael@0: { SEC_ASN1_OBJECT_ID, michael@0: offsetof(CERTPolicyQualifier, qualifierID) }, michael@0: { SEC_ASN1_ANY, michael@0: offsetof(CERTPolicyQualifier, qualifierValue) }, michael@0: { 0 } michael@0: }; michael@0: michael@0: const SEC_ASN1Template CERT_PolicyInfoTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, michael@0: 0, NULL, sizeof(CERTPolicyInfo) }, michael@0: { SEC_ASN1_OBJECT_ID, michael@0: offsetof(CERTPolicyInfo, policyID) }, michael@0: { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL, michael@0: offsetof(CERTPolicyInfo, policyQualifiers), michael@0: CERT_PolicyQualifierTemplate }, michael@0: { 0 } michael@0: }; michael@0: michael@0: const SEC_ASN1Template CERT_CertificatePoliciesTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE_OF, michael@0: offsetof(CERTCertificatePolicies, policyInfos), michael@0: CERT_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) } michael@0: }; michael@0: michael@0: const SEC_ASN1Template CERT_PolicyMapTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, michael@0: 0, NULL, sizeof(CERTPolicyMap) }, michael@0: { SEC_ASN1_OBJECT_ID, michael@0: offsetof(CERTPolicyMap, issuerDomainPolicy) }, michael@0: { SEC_ASN1_OBJECT_ID, michael@0: offsetof(CERTPolicyMap, subjectDomainPolicy) }, michael@0: { 0 } michael@0: }; michael@0: michael@0: const SEC_ASN1Template CERT_PolicyMappingsTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE_OF, michael@0: offsetof(CERTCertificatePolicyMappings, policyMaps), michael@0: CERT_PolicyMapTemplate, sizeof(CERTPolicyMap) } michael@0: }; michael@0: michael@0: const SEC_ASN1Template CERT_PolicyConstraintsTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCertificatePolicyConstraints) }, michael@0: { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, michael@0: offsetof(CERTCertificatePolicyConstraints, explicitPolicySkipCerts), michael@0: SEC_ASN1_SUB(SEC_IntegerTemplate) }, michael@0: { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, michael@0: offsetof(CERTCertificatePolicyConstraints, inhibitMappingSkipCerts), michael@0: SEC_ASN1_SUB(SEC_IntegerTemplate) }, michael@0: { 0 } michael@0: }; michael@0: michael@0: const SEC_ASN1Template CERT_InhibitAnyTemplate[] = { michael@0: { SEC_ASN1_INTEGER, michael@0: offsetof(CERTCertificateInhibitAny, inhibitAnySkipCerts), michael@0: NULL, sizeof(CERTCertificateInhibitAny) } michael@0: }; michael@0: michael@0: static void michael@0: breakLines(char *string) michael@0: { michael@0: char *tmpstr; michael@0: char *lastspace = NULL; michael@0: int curlen = 0; michael@0: int c; michael@0: michael@0: tmpstr = string; michael@0: michael@0: while ( ( c = *tmpstr ) != '\0' ) { michael@0: switch ( c ) { michael@0: case ' ': michael@0: lastspace = tmpstr; michael@0: break; michael@0: case '\n': michael@0: lastspace = NULL; michael@0: curlen = 0; michael@0: break; michael@0: } michael@0: michael@0: if ( ( curlen >= 55 ) && ( lastspace != NULL ) ) { michael@0: *lastspace = '\n'; michael@0: curlen = ( tmpstr - lastspace ); michael@0: lastspace = NULL; michael@0: } michael@0: michael@0: curlen++; michael@0: tmpstr++; michael@0: } michael@0: michael@0: return; michael@0: } michael@0: michael@0: CERTCertificatePolicies * michael@0: CERT_DecodeCertificatePoliciesExtension(const SECItem *extnValue) michael@0: { michael@0: PLArenaPool *arena = NULL; michael@0: SECStatus rv; michael@0: CERTCertificatePolicies *policies; michael@0: CERTPolicyInfo **policyInfos, *policyInfo; michael@0: CERTPolicyQualifier **policyQualifiers, *policyQualifier; michael@0: SECItem newExtnValue; michael@0: michael@0: /* make a new arena */ michael@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); michael@0: michael@0: if ( !arena ) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* allocate the certificate policies structure */ michael@0: policies = (CERTCertificatePolicies *) michael@0: PORT_ArenaZAlloc(arena, sizeof(CERTCertificatePolicies)); michael@0: michael@0: if ( policies == NULL ) { michael@0: goto loser; michael@0: } michael@0: michael@0: policies->arena = arena; michael@0: michael@0: /* copy the DER into the arena, since Quick DER returns data that points michael@0: into the DER input, which may get freed by the caller */ michael@0: rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue); michael@0: if ( rv != SECSuccess ) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* decode the policy info */ michael@0: rv = SEC_QuickDERDecodeItem(arena, policies, CERT_CertificatePoliciesTemplate, michael@0: &newExtnValue); michael@0: michael@0: if ( rv != SECSuccess ) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* initialize the oid tags */ michael@0: policyInfos = policies->policyInfos; michael@0: while (*policyInfos != NULL ) { michael@0: policyInfo = *policyInfos; michael@0: policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID); michael@0: policyQualifiers = policyInfo->policyQualifiers; michael@0: while ( policyQualifiers != NULL && *policyQualifiers != NULL ) { michael@0: policyQualifier = *policyQualifiers; michael@0: policyQualifier->oid = michael@0: SECOID_FindOIDTag(&policyQualifier->qualifierID); michael@0: policyQualifiers++; michael@0: } michael@0: policyInfos++; michael@0: } michael@0: michael@0: return(policies); michael@0: michael@0: loser: michael@0: if ( arena != NULL ) { michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: } michael@0: michael@0: return(NULL); michael@0: } michael@0: michael@0: void michael@0: CERT_DestroyCertificatePoliciesExtension(CERTCertificatePolicies *policies) michael@0: { michael@0: if ( policies != NULL ) { michael@0: PORT_FreeArena(policies->arena, PR_FALSE); michael@0: } michael@0: return; michael@0: } michael@0: michael@0: CERTCertificatePolicyMappings * michael@0: CERT_DecodePolicyMappingsExtension(SECItem *extnValue) michael@0: { michael@0: PLArenaPool *arena = NULL; michael@0: SECStatus rv; michael@0: CERTCertificatePolicyMappings *mappings; michael@0: SECItem newExtnValue; michael@0: michael@0: /* make a new arena */ michael@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); michael@0: if ( !arena ) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* allocate the policy mappings structure */ michael@0: mappings = (CERTCertificatePolicyMappings *) michael@0: PORT_ArenaZAlloc(arena, sizeof(CERTCertificatePolicyMappings)); michael@0: if ( mappings == NULL ) { michael@0: goto loser; michael@0: } michael@0: mappings->arena = arena; michael@0: michael@0: /* copy the DER into the arena, since Quick DER returns data that points michael@0: into the DER input, which may get freed by the caller */ michael@0: rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue); michael@0: if ( rv != SECSuccess ) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* decode the policy mappings */ michael@0: rv = SEC_QuickDERDecodeItem michael@0: (arena, mappings, CERT_PolicyMappingsTemplate, &newExtnValue); michael@0: if ( rv != SECSuccess ) { michael@0: goto loser; michael@0: } michael@0: michael@0: return(mappings); michael@0: michael@0: loser: michael@0: if ( arena != NULL ) { michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: } michael@0: michael@0: return(NULL); michael@0: } michael@0: michael@0: SECStatus michael@0: CERT_DestroyPolicyMappingsExtension(CERTCertificatePolicyMappings *mappings) michael@0: { michael@0: if ( mappings != NULL ) { michael@0: PORT_FreeArena(mappings->arena, PR_FALSE); michael@0: } michael@0: return SECSuccess; michael@0: } michael@0: michael@0: SECStatus michael@0: CERT_DecodePolicyConstraintsExtension michael@0: (CERTCertificatePolicyConstraints *decodedValue, michael@0: const SECItem *encodedValue) michael@0: { michael@0: CERTCertificatePolicyConstraints decodeContext; michael@0: PLArenaPool *arena = NULL; michael@0: SECStatus rv = SECSuccess; michael@0: michael@0: /* initialize so we can tell when an optional component is omitted */ michael@0: PORT_Memset(&decodeContext, 0, sizeof(decodeContext)); michael@0: michael@0: /* make a new arena */ michael@0: arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); michael@0: if (!arena) { michael@0: return SECFailure; michael@0: } michael@0: michael@0: do { michael@0: /* decode the policy constraints */ michael@0: rv = SEC_QuickDERDecodeItem(arena, michael@0: &decodeContext, CERT_PolicyConstraintsTemplate, encodedValue); michael@0: michael@0: if ( rv != SECSuccess ) { michael@0: break; michael@0: } michael@0: michael@0: if (decodeContext.explicitPolicySkipCerts.len == 0) { michael@0: *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = -1; michael@0: } else { michael@0: *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = michael@0: DER_GetInteger(&decodeContext.explicitPolicySkipCerts); michael@0: } michael@0: michael@0: if (decodeContext.inhibitMappingSkipCerts.len == 0) { michael@0: *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = -1; michael@0: } else { michael@0: *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = michael@0: DER_GetInteger(&decodeContext.inhibitMappingSkipCerts); michael@0: } michael@0: michael@0: if ((*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data == michael@0: PR_INT32_MIN) || michael@0: (*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data == michael@0: PR_INT32_MAX) || michael@0: (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data == michael@0: PR_INT32_MIN) || michael@0: (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data == michael@0: PR_INT32_MAX)) { michael@0: rv = SECFailure; michael@0: } michael@0: michael@0: } while (0); michael@0: michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: return(rv); michael@0: } michael@0: michael@0: SECStatus CERT_DecodeInhibitAnyExtension michael@0: (CERTCertificateInhibitAny *decodedValue, SECItem *encodedValue) michael@0: { michael@0: CERTCertificateInhibitAny decodeContext; michael@0: PLArenaPool *arena = NULL; michael@0: SECStatus rv = SECSuccess; michael@0: michael@0: /* make a new arena */ michael@0: arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); michael@0: if ( !arena ) { michael@0: return SECFailure; michael@0: } michael@0: michael@0: do { michael@0: michael@0: /* decode the policy mappings */ michael@0: decodeContext.inhibitAnySkipCerts.type = siUnsignedInteger; michael@0: rv = SEC_QuickDERDecodeItem(arena, michael@0: &decodeContext, CERT_InhibitAnyTemplate, encodedValue); michael@0: michael@0: if ( rv != SECSuccess ) { michael@0: break; michael@0: } michael@0: michael@0: *(PRInt32 *)decodedValue->inhibitAnySkipCerts.data = michael@0: DER_GetInteger(&decodeContext.inhibitAnySkipCerts); michael@0: michael@0: } while (0); michael@0: michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: return(rv); michael@0: } michael@0: michael@0: CERTUserNotice * michael@0: CERT_DecodeUserNotice(SECItem *noticeItem) michael@0: { michael@0: PLArenaPool *arena = NULL; michael@0: SECStatus rv; michael@0: CERTUserNotice *userNotice; michael@0: SECItem newNoticeItem; michael@0: michael@0: /* make a new arena */ michael@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); michael@0: michael@0: if ( !arena ) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* allocate the userNotice structure */ michael@0: userNotice = (CERTUserNotice *)PORT_ArenaZAlloc(arena, michael@0: sizeof(CERTUserNotice)); michael@0: michael@0: if ( userNotice == NULL ) { michael@0: goto loser; michael@0: } michael@0: michael@0: userNotice->arena = arena; michael@0: michael@0: /* copy the DER into the arena, since Quick DER returns data that points michael@0: into the DER input, which may get freed by the caller */ michael@0: rv = SECITEM_CopyItem(arena, &newNoticeItem, noticeItem); michael@0: if ( rv != SECSuccess ) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* decode the user notice */ michael@0: rv = SEC_QuickDERDecodeItem(arena, userNotice, CERT_UserNoticeTemplate, michael@0: &newNoticeItem); michael@0: michael@0: if ( rv != SECSuccess ) { michael@0: goto loser; michael@0: } michael@0: michael@0: if (userNotice->derNoticeReference.data != NULL) { michael@0: michael@0: rv = SEC_QuickDERDecodeItem(arena, &userNotice->noticeReference, michael@0: CERT_NoticeReferenceTemplate, michael@0: &userNotice->derNoticeReference); michael@0: if (rv == SECFailure) { michael@0: goto loser; michael@0: } michael@0: } michael@0: michael@0: return(userNotice); michael@0: michael@0: loser: michael@0: if ( arena != NULL ) { michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: } michael@0: michael@0: return(NULL); michael@0: } michael@0: michael@0: void michael@0: CERT_DestroyUserNotice(CERTUserNotice *userNotice) michael@0: { michael@0: if ( userNotice != NULL ) { michael@0: PORT_FreeArena(userNotice->arena, PR_FALSE); michael@0: } michael@0: return; michael@0: } michael@0: michael@0: static CERTPolicyStringCallback policyStringCB = NULL; michael@0: static void *policyStringCBArg = NULL; michael@0: michael@0: void michael@0: CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg) michael@0: { michael@0: policyStringCB = cb; michael@0: policyStringCBArg = cbarg; michael@0: return; michael@0: } michael@0: michael@0: char * michael@0: stringFromUserNotice(SECItem *noticeItem) michael@0: { michael@0: SECItem *org; michael@0: unsigned int len, headerlen; michael@0: char *stringbuf; michael@0: CERTUserNotice *userNotice; michael@0: char *policystr; michael@0: char *retstr = NULL; michael@0: SECItem *displayText; michael@0: SECItem **noticeNumbers; michael@0: unsigned int strnum; michael@0: michael@0: /* decode the user notice */ michael@0: userNotice = CERT_DecodeUserNotice(noticeItem); michael@0: if ( userNotice == NULL ) { michael@0: return(NULL); michael@0: } michael@0: michael@0: org = &userNotice->noticeReference.organization; michael@0: if ( (org->len != 0 ) && ( policyStringCB != NULL ) ) { michael@0: /* has a noticeReference */ michael@0: michael@0: /* extract the org string */ michael@0: len = org->len; michael@0: stringbuf = (char*)PORT_Alloc(len + 1); michael@0: if ( stringbuf != NULL ) { michael@0: PORT_Memcpy(stringbuf, org->data, len); michael@0: stringbuf[len] = '\0'; michael@0: michael@0: noticeNumbers = userNotice->noticeReference.noticeNumbers; michael@0: while ( *noticeNumbers != NULL ) { michael@0: /* XXX - only one byte integers right now*/ michael@0: strnum = (*noticeNumbers)->data[0]; michael@0: policystr = (* policyStringCB)(stringbuf, michael@0: strnum, michael@0: policyStringCBArg); michael@0: if ( policystr != NULL ) { michael@0: if ( retstr != NULL ) { michael@0: retstr = PR_sprintf_append(retstr, "\n%s", policystr); michael@0: } else { michael@0: retstr = PR_sprintf_append(retstr, "%s", policystr); michael@0: } michael@0: michael@0: PORT_Free(policystr); michael@0: } michael@0: michael@0: noticeNumbers++; michael@0: } michael@0: michael@0: PORT_Free(stringbuf); michael@0: } michael@0: } michael@0: michael@0: if ( retstr == NULL ) { michael@0: if ( userNotice->displayText.len != 0 ) { michael@0: displayText = &userNotice->displayText; michael@0: michael@0: if ( displayText->len > 2 ) { michael@0: if ( displayText->data[0] == SEC_ASN1_VISIBLE_STRING ) { michael@0: headerlen = 2; michael@0: if ( displayText->data[1] & 0x80 ) { michael@0: /* multibyte length */ michael@0: headerlen += ( displayText->data[1] & 0x7f ); michael@0: } michael@0: michael@0: len = displayText->len - headerlen; michael@0: retstr = (char*)PORT_Alloc(len + 1); michael@0: if ( retstr != NULL ) { michael@0: PORT_Memcpy(retstr, &displayText->data[headerlen],len); michael@0: retstr[len] = '\0'; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: CERT_DestroyUserNotice(userNotice); michael@0: michael@0: return(retstr); michael@0: } michael@0: michael@0: char * michael@0: CERT_GetCertCommentString(CERTCertificate *cert) michael@0: { michael@0: char *retstring = NULL; michael@0: SECStatus rv; michael@0: SECItem policyItem; michael@0: CERTCertificatePolicies *policies = NULL; michael@0: CERTPolicyInfo **policyInfos; michael@0: CERTPolicyQualifier **policyQualifiers, *qualifier; michael@0: michael@0: policyItem.data = NULL; michael@0: michael@0: rv = CERT_FindCertExtension(cert, SEC_OID_X509_CERTIFICATE_POLICIES, michael@0: &policyItem); michael@0: if ( rv != SECSuccess ) { michael@0: goto nopolicy; michael@0: } michael@0: michael@0: policies = CERT_DecodeCertificatePoliciesExtension(&policyItem); michael@0: if ( policies == NULL ) { michael@0: goto nopolicy; michael@0: } michael@0: michael@0: policyInfos = policies->policyInfos; michael@0: /* search through policyInfos looking for the verisign policy */ michael@0: while (*policyInfos != NULL ) { michael@0: if ( (*policyInfos)->oid == SEC_OID_VERISIGN_USER_NOTICES ) { michael@0: policyQualifiers = (*policyInfos)->policyQualifiers; michael@0: /* search through the policy qualifiers looking for user notice */ michael@0: while ( policyQualifiers != NULL && *policyQualifiers != NULL ) { michael@0: qualifier = *policyQualifiers; michael@0: if ( qualifier->oid == SEC_OID_PKIX_USER_NOTICE_QUALIFIER ) { michael@0: retstring = michael@0: stringFromUserNotice(&qualifier->qualifierValue); michael@0: break; michael@0: } michael@0: michael@0: policyQualifiers++; michael@0: } michael@0: break; michael@0: } michael@0: policyInfos++; michael@0: } michael@0: michael@0: nopolicy: michael@0: if ( policyItem.data != NULL ) { michael@0: PORT_Free(policyItem.data); michael@0: } michael@0: michael@0: if ( policies != NULL ) { michael@0: CERT_DestroyCertificatePoliciesExtension(policies); michael@0: } michael@0: michael@0: if ( retstring == NULL ) { michael@0: retstring = CERT_FindNSStringExtension(cert, michael@0: SEC_OID_NS_CERT_EXT_COMMENT); michael@0: } michael@0: michael@0: if ( retstring != NULL ) { michael@0: breakLines(retstring); michael@0: } michael@0: michael@0: return(retstring); michael@0: } michael@0: michael@0: michael@0: const SEC_ASN1Template CERT_OidSeqTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, michael@0: offsetof(CERTOidSequence, oids), michael@0: SEC_ASN1_SUB(SEC_ObjectIDTemplate) } michael@0: }; michael@0: michael@0: CERTOidSequence * michael@0: CERT_DecodeOidSequence(const SECItem *seqItem) michael@0: { michael@0: PLArenaPool *arena = NULL; michael@0: SECStatus rv; michael@0: CERTOidSequence *oidSeq; michael@0: SECItem newSeqItem; michael@0: michael@0: /* make a new arena */ michael@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); michael@0: michael@0: if ( !arena ) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* allocate the userNotice structure */ michael@0: oidSeq = (CERTOidSequence *)PORT_ArenaZAlloc(arena, michael@0: sizeof(CERTOidSequence)); michael@0: michael@0: if ( oidSeq == NULL ) { michael@0: goto loser; michael@0: } michael@0: michael@0: oidSeq->arena = arena; michael@0: michael@0: /* copy the DER into the arena, since Quick DER returns data that points michael@0: into the DER input, which may get freed by the caller */ michael@0: rv = SECITEM_CopyItem(arena, &newSeqItem, seqItem); michael@0: if ( rv != SECSuccess ) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* decode the user notice */ michael@0: rv = SEC_QuickDERDecodeItem(arena, oidSeq, CERT_OidSeqTemplate, &newSeqItem); michael@0: michael@0: if ( rv != SECSuccess ) { michael@0: goto loser; michael@0: } michael@0: michael@0: return(oidSeq); michael@0: michael@0: loser: michael@0: if (arena) { michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: } michael@0: return(NULL); michael@0: } michael@0: michael@0: michael@0: void michael@0: CERT_DestroyOidSequence(CERTOidSequence *oidSeq) michael@0: { michael@0: if ( oidSeq != NULL ) { michael@0: PORT_FreeArena(oidSeq->arena, PR_FALSE); michael@0: } michael@0: return; michael@0: } michael@0: michael@0: PRBool michael@0: CERT_GovtApprovedBitSet(CERTCertificate *cert) michael@0: { michael@0: SECStatus rv; michael@0: SECItem extItem; michael@0: CERTOidSequence *oidSeq = NULL; michael@0: PRBool ret; michael@0: SECItem **oids; michael@0: SECItem *oid; michael@0: SECOidTag oidTag; michael@0: michael@0: extItem.data = NULL; michael@0: rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem); michael@0: if ( rv != SECSuccess ) { michael@0: goto loser; michael@0: } michael@0: michael@0: oidSeq = CERT_DecodeOidSequence(&extItem); michael@0: if ( oidSeq == NULL ) { michael@0: goto loser; michael@0: } michael@0: michael@0: oids = oidSeq->oids; michael@0: while ( oids != NULL && *oids != NULL ) { michael@0: oid = *oids; michael@0: michael@0: oidTag = SECOID_FindOIDTag(oid); michael@0: michael@0: if ( oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED ) { michael@0: goto success; michael@0: } michael@0: michael@0: oids++; michael@0: } michael@0: michael@0: loser: michael@0: ret = PR_FALSE; michael@0: goto done; michael@0: success: michael@0: ret = PR_TRUE; michael@0: done: michael@0: if ( oidSeq != NULL ) { michael@0: CERT_DestroyOidSequence(oidSeq); michael@0: } michael@0: if (extItem.data != NULL) { michael@0: PORT_Free(extItem.data); michael@0: } michael@0: return(ret); michael@0: } michael@0: michael@0: michael@0: SECStatus michael@0: CERT_EncodePolicyConstraintsExtension(PLArenaPool *arena, michael@0: CERTCertificatePolicyConstraints *constr, michael@0: SECItem *dest) michael@0: { michael@0: SECStatus rv = SECSuccess; michael@0: michael@0: PORT_Assert(constr != NULL && dest != NULL); michael@0: if (constr == NULL || dest == NULL) { michael@0: return SECFailure; michael@0: } michael@0: michael@0: if (SEC_ASN1EncodeItem (arena, dest, constr, michael@0: CERT_PolicyConstraintsTemplate) == NULL) { michael@0: rv = SECFailure; michael@0: } michael@0: return(rv); michael@0: } michael@0: michael@0: SECStatus michael@0: CERT_EncodePolicyMappingExtension(PLArenaPool *arena, michael@0: CERTCertificatePolicyMappings *mapping, michael@0: SECItem *dest) michael@0: { michael@0: SECStatus rv = SECSuccess; michael@0: michael@0: PORT_Assert(mapping != NULL && dest != NULL); michael@0: if (mapping == NULL || dest == NULL) { michael@0: return SECFailure; michael@0: } michael@0: michael@0: if (SEC_ASN1EncodeItem (arena, dest, mapping, michael@0: CERT_PolicyMappingsTemplate) == NULL) { michael@0: rv = SECFailure; michael@0: } michael@0: return(rv); michael@0: } michael@0: michael@0: michael@0: michael@0: SECStatus michael@0: CERT_EncodeCertPoliciesExtension(PLArenaPool *arena, michael@0: CERTPolicyInfo **info, michael@0: SECItem *dest) michael@0: { michael@0: SECStatus rv = SECSuccess; michael@0: michael@0: PORT_Assert(info != NULL && dest != NULL); michael@0: if (info == NULL || dest == NULL) { michael@0: return SECFailure; michael@0: } michael@0: michael@0: if (SEC_ASN1EncodeItem (arena, dest, info, michael@0: CERT_CertificatePoliciesTemplate) == NULL) { michael@0: rv = SECFailure; michael@0: } michael@0: return(rv); michael@0: } michael@0: michael@0: SECStatus michael@0: CERT_EncodeUserNotice(PLArenaPool *arena, michael@0: CERTUserNotice *notice, michael@0: SECItem *dest) michael@0: { michael@0: SECStatus rv = SECSuccess; michael@0: michael@0: PORT_Assert(notice != NULL && dest != NULL); michael@0: if (notice == NULL || dest == NULL) { michael@0: return SECFailure; michael@0: } michael@0: michael@0: if (SEC_ASN1EncodeItem(arena, dest, michael@0: notice, CERT_UserNoticeTemplate) == NULL) { michael@0: rv = SECFailure; michael@0: } michael@0: michael@0: return(rv); michael@0: } michael@0: michael@0: SECStatus michael@0: CERT_EncodeNoticeReference(PLArenaPool *arena, michael@0: CERTNoticeReference *reference, michael@0: SECItem *dest) michael@0: { michael@0: SECStatus rv = SECSuccess; michael@0: michael@0: PORT_Assert(reference != NULL && dest != NULL); michael@0: if (reference == NULL || dest == NULL) { michael@0: return SECFailure; michael@0: } michael@0: michael@0: if (SEC_ASN1EncodeItem (arena, dest, reference, michael@0: CERT_NoticeReferenceTemplate) == NULL) { michael@0: rv = SECFailure; michael@0: } michael@0: michael@0: return(rv); michael@0: } michael@0: michael@0: SECStatus michael@0: CERT_EncodeInhibitAnyExtension(PLArenaPool *arena, michael@0: CERTCertificateInhibitAny *certInhibitAny, michael@0: SECItem *dest) michael@0: { michael@0: SECStatus rv = SECSuccess; michael@0: michael@0: PORT_Assert(certInhibitAny != NULL && dest != NULL); michael@0: if (certInhibitAny == NULL || dest == NULL) { michael@0: return SECFailure; michael@0: } michael@0: michael@0: if (SEC_ASN1EncodeItem (arena, dest, certInhibitAny, michael@0: CERT_InhibitAnyTemplate) == NULL) { michael@0: rv = SECFailure; michael@0: } michael@0: return(rv); michael@0: }