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