tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

polcyxtn.c (21846B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /*
      6 * Support for various policy related extensions
      7 */
      8 
      9 #include "seccomon.h"
     10 #include "secport.h"
     11 #include "secder.h"
     12 #include "cert.h"
     13 #include "secoid.h"
     14 #include "secasn1.h"
     15 #include "secerr.h"
     16 #include "nspr.h"
     17 
     18 SEC_ASN1_MKSUB(SEC_IntegerTemplate)
     19 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
     20 
     21 const SEC_ASN1Template CERT_DisplayTextTypeTemplate[] = {
     22    { SEC_ASN1_CHOICE, offsetof(SECItem, type), 0, sizeof(SECItem) },
     23    { SEC_ASN1_IA5_STRING, 0, 0, siAsciiString },
     24    { SEC_ASN1_VISIBLE_STRING, 0, 0, siVisibleString },
     25    { SEC_ASN1_BMP_STRING, 0, 0, siBMPString },
     26    { SEC_ASN1_UTF8_STRING, 0, 0, siUTF8String },
     27    { 0 }
     28 };
     29 
     30 const SEC_ASN1Template CERT_NoticeReferenceTemplate[] = {
     31    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNoticeReference) },
     32    { SEC_ASN1_INLINE, offsetof(CERTNoticeReference, organization),
     33      CERT_DisplayTextTypeTemplate, 0 },
     34    { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN,
     35      offsetof(CERTNoticeReference, noticeNumbers),
     36      SEC_ASN1_SUB(SEC_IntegerTemplate) },
     37    { 0 }
     38 };
     39 
     40 const SEC_ASN1Template CERT_UserNoticeTemplate[] = {
     41    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTUserNotice) },
     42    { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
     43      offsetof(CERTUserNotice, noticeReference), CERT_NoticeReferenceTemplate,
     44      0 },
     45    { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
     46      offsetof(CERTUserNotice, displayText), CERT_DisplayTextTypeTemplate, 0 },
     47    { 0 }
     48 };
     49 
     50 const SEC_ASN1Template CERT_PolicyQualifierTemplate[] = {
     51    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPolicyQualifier) },
     52    { SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyQualifier, qualifierID) },
     53    { SEC_ASN1_ANY, offsetof(CERTPolicyQualifier, qualifierValue) },
     54    { 0 }
     55 };
     56 
     57 const SEC_ASN1Template CERT_PolicyInfoTemplate[] = {
     58    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPolicyInfo) },
     59    { SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyInfo, policyID) },
     60    { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
     61      offsetof(CERTPolicyInfo, policyQualifiers),
     62      CERT_PolicyQualifierTemplate },
     63    { 0 }
     64 };
     65 
     66 const SEC_ASN1Template CERT_CertificatePoliciesTemplate[] = {
     67    { SEC_ASN1_SEQUENCE_OF, offsetof(CERTCertificatePolicies, policyInfos),
     68      CERT_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) }
     69 };
     70 
     71 const SEC_ASN1Template CERT_PolicyMapTemplate[] = {
     72    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPolicyMap) },
     73    { SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyMap, issuerDomainPolicy) },
     74    { SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyMap, subjectDomainPolicy) },
     75    { 0 }
     76 };
     77 
     78 const SEC_ASN1Template CERT_PolicyMappingsTemplate[] = {
     79    { SEC_ASN1_SEQUENCE_OF, offsetof(CERTCertificatePolicyMappings, policyMaps),
     80      CERT_PolicyMapTemplate, sizeof(CERTPolicyMap) }
     81 };
     82 
     83 const SEC_ASN1Template CERT_PolicyConstraintsTemplate[] = {
     84    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCertificatePolicyConstraints) },
     85    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
     86      offsetof(CERTCertificatePolicyConstraints, explicitPolicySkipCerts),
     87      SEC_ASN1_SUB(SEC_IntegerTemplate) },
     88    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
     89      offsetof(CERTCertificatePolicyConstraints, inhibitMappingSkipCerts),
     90      SEC_ASN1_SUB(SEC_IntegerTemplate) },
     91    { 0 }
     92 };
     93 
     94 const SEC_ASN1Template CERT_InhibitAnyTemplate[] = {
     95    { SEC_ASN1_INTEGER,
     96      offsetof(CERTCertificateInhibitAny, inhibitAnySkipCerts), NULL,
     97      sizeof(CERTCertificateInhibitAny) }
     98 };
     99 
    100 static void
    101 breakLines(char *string)
    102 {
    103    char *tmpstr;
    104    char *lastspace = NULL;
    105    int curlen = 0;
    106    int c;
    107 
    108    tmpstr = string;
    109 
    110    while ((c = *tmpstr) != '\0') {
    111        switch (c) {
    112            case ' ':
    113                lastspace = tmpstr;
    114                break;
    115            case '\n':
    116                lastspace = NULL;
    117                curlen = 0;
    118                break;
    119        }
    120 
    121        if ((curlen >= 55) && (lastspace != NULL)) {
    122            *lastspace = '\n';
    123            curlen = (tmpstr - lastspace);
    124            lastspace = NULL;
    125        }
    126 
    127        curlen++;
    128        tmpstr++;
    129    }
    130 
    131    return;
    132 }
    133 
    134 CERTCertificatePolicies *
    135 CERT_DecodeCertificatePoliciesExtension(const SECItem *extnValue)
    136 {
    137    PLArenaPool *arena = NULL;
    138    SECStatus rv;
    139    CERTCertificatePolicies *policies;
    140    CERTPolicyInfo **policyInfos, *policyInfo;
    141    CERTPolicyQualifier **policyQualifiers, *policyQualifier;
    142    SECItem newExtnValue;
    143 
    144    /* make a new arena */
    145    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    146 
    147    if (!arena) {
    148        goto loser;
    149    }
    150 
    151    /* allocate the certificate policies structure */
    152    policies = (CERTCertificatePolicies *)PORT_ArenaZAlloc(
    153        arena, sizeof(CERTCertificatePolicies));
    154 
    155    if (policies == NULL) {
    156        goto loser;
    157    }
    158 
    159    policies->arena = arena;
    160 
    161    /* copy the DER into the arena, since Quick DER returns data that points
    162       into the DER input, which may get freed by the caller */
    163    rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
    164    if (rv != SECSuccess) {
    165        goto loser;
    166    }
    167 
    168    /* decode the policy info */
    169    rv = SEC_QuickDERDecodeItem(
    170        arena, policies, CERT_CertificatePoliciesTemplate, &newExtnValue);
    171 
    172    if (rv != SECSuccess) {
    173        goto loser;
    174    }
    175 
    176    /* initialize the oid tags */
    177    policyInfos = policies->policyInfos;
    178    while (*policyInfos != NULL) {
    179        policyInfo = *policyInfos;
    180        policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
    181        policyQualifiers = policyInfo->policyQualifiers;
    182        while (policyQualifiers != NULL && *policyQualifiers != NULL) {
    183            policyQualifier = *policyQualifiers;
    184            policyQualifier->oid =
    185                SECOID_FindOIDTag(&policyQualifier->qualifierID);
    186            policyQualifiers++;
    187        }
    188        policyInfos++;
    189    }
    190 
    191    return (policies);
    192 
    193 loser:
    194    if (arena != NULL) {
    195        PORT_FreeArena(arena, PR_FALSE);
    196    }
    197 
    198    return (NULL);
    199 }
    200 
    201 void
    202 CERT_DestroyCertificatePoliciesExtension(CERTCertificatePolicies *policies)
    203 {
    204    if (policies != NULL) {
    205        PORT_FreeArena(policies->arena, PR_FALSE);
    206    }
    207    return;
    208 }
    209 
    210 CERTCertificatePolicyMappings *
    211 CERT_DecodePolicyMappingsExtension(SECItem *extnValue)
    212 {
    213    PLArenaPool *arena = NULL;
    214    SECStatus rv;
    215    CERTCertificatePolicyMappings *mappings;
    216    SECItem newExtnValue;
    217 
    218    /* make a new arena */
    219    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    220    if (!arena) {
    221        goto loser;
    222    }
    223 
    224    /* allocate the policy mappings structure */
    225    mappings = (CERTCertificatePolicyMappings *)PORT_ArenaZAlloc(
    226        arena, sizeof(CERTCertificatePolicyMappings));
    227    if (mappings == NULL) {
    228        goto loser;
    229    }
    230    mappings->arena = arena;
    231 
    232    /* copy the DER into the arena, since Quick DER returns data that points
    233       into the DER input, which may get freed by the caller */
    234    rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
    235    if (rv != SECSuccess) {
    236        goto loser;
    237    }
    238 
    239    /* decode the policy mappings */
    240    rv = SEC_QuickDERDecodeItem(arena, mappings, CERT_PolicyMappingsTemplate,
    241                                &newExtnValue);
    242    if (rv != SECSuccess) {
    243        goto loser;
    244    }
    245 
    246    return (mappings);
    247 
    248 loser:
    249    if (arena != NULL) {
    250        PORT_FreeArena(arena, PR_FALSE);
    251    }
    252 
    253    return (NULL);
    254 }
    255 
    256 SECStatus
    257 CERT_DestroyPolicyMappingsExtension(CERTCertificatePolicyMappings *mappings)
    258 {
    259    if (mappings != NULL) {
    260        PORT_FreeArena(mappings->arena, PR_FALSE);
    261    }
    262    return SECSuccess;
    263 }
    264 
    265 SECStatus
    266 CERT_DecodePolicyConstraintsExtension(
    267    CERTCertificatePolicyConstraints *decodedValue, const SECItem *encodedValue)
    268 {
    269    CERTCertificatePolicyConstraints decodeContext;
    270    PLArenaPool *arena = NULL;
    271    SECStatus rv = SECSuccess;
    272 
    273    /* initialize so we can tell when an optional component is omitted */
    274    PORT_Memset(&decodeContext, 0, sizeof(decodeContext));
    275 
    276    /* make a new arena */
    277    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    278    if (!arena) {
    279        return SECFailure;
    280    }
    281 
    282    do {
    283        /* decode the policy constraints */
    284        rv = SEC_QuickDERDecodeItem(arena, &decodeContext,
    285                                    CERT_PolicyConstraintsTemplate,
    286                                    encodedValue);
    287 
    288        if (rv != SECSuccess) {
    289            break;
    290        }
    291 
    292        if (decodeContext.explicitPolicySkipCerts.len == 0) {
    293            *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = -1;
    294        } else {
    295            *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data =
    296                DER_GetInteger(&decodeContext.explicitPolicySkipCerts);
    297        }
    298 
    299        if (decodeContext.inhibitMappingSkipCerts.len == 0) {
    300            *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = -1;
    301        } else {
    302            *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data =
    303                DER_GetInteger(&decodeContext.inhibitMappingSkipCerts);
    304        }
    305 
    306        if ((*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data ==
    307             PR_INT32_MIN) ||
    308            (*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data ==
    309             PR_INT32_MAX) ||
    310            (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data ==
    311             PR_INT32_MIN) ||
    312            (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data ==
    313             PR_INT32_MAX)) {
    314            rv = SECFailure;
    315        }
    316 
    317    } while (0);
    318 
    319    PORT_FreeArena(arena, PR_FALSE);
    320    return (rv);
    321 }
    322 
    323 SECStatus
    324 CERT_DecodeInhibitAnyExtension(CERTCertificateInhibitAny *decodedValue,
    325                               SECItem *encodedValue)
    326 {
    327    CERTCertificateInhibitAny decodeContext;
    328    PLArenaPool *arena = NULL;
    329    SECStatus rv = SECSuccess;
    330 
    331    /* make a new arena */
    332    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    333    if (!arena) {
    334        return SECFailure;
    335    }
    336 
    337    do {
    338 
    339        /* decode the policy mappings */
    340        decodeContext.inhibitAnySkipCerts.type = siUnsignedInteger;
    341        rv = SEC_QuickDERDecodeItem(arena, &decodeContext,
    342                                    CERT_InhibitAnyTemplate, encodedValue);
    343 
    344        if (rv != SECSuccess) {
    345            break;
    346        }
    347 
    348        *(PRInt32 *)decodedValue->inhibitAnySkipCerts.data =
    349            DER_GetInteger(&decodeContext.inhibitAnySkipCerts);
    350 
    351    } while (0);
    352 
    353    PORT_FreeArena(arena, PR_FALSE);
    354    return (rv);
    355 }
    356 
    357 CERTUserNotice *
    358 CERT_DecodeUserNotice(SECItem *noticeItem)
    359 {
    360    PLArenaPool *arena = NULL;
    361    SECStatus rv;
    362    CERTUserNotice *userNotice;
    363    SECItem newNoticeItem;
    364 
    365    /* make a new arena */
    366    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    367 
    368    if (!arena) {
    369        goto loser;
    370    }
    371 
    372    /* allocate the userNotice structure */
    373    userNotice =
    374        (CERTUserNotice *)PORT_ArenaZAlloc(arena, sizeof(CERTUserNotice));
    375 
    376    if (userNotice == NULL) {
    377        goto loser;
    378    }
    379 
    380    userNotice->arena = arena;
    381 
    382    /* copy the DER into the arena, since Quick DER returns data that points
    383       into the DER input, which may get freed by the caller */
    384    rv = SECITEM_CopyItem(arena, &newNoticeItem, noticeItem);
    385    if (rv != SECSuccess) {
    386        goto loser;
    387    }
    388 
    389    /* decode the user notice */
    390    rv = SEC_QuickDERDecodeItem(arena, userNotice, CERT_UserNoticeTemplate,
    391                                &newNoticeItem);
    392 
    393    if (rv != SECSuccess) {
    394        goto loser;
    395    }
    396 
    397    if (userNotice->derNoticeReference.data != NULL) {
    398 
    399        rv = SEC_QuickDERDecodeItem(arena, &userNotice->noticeReference,
    400                                    CERT_NoticeReferenceTemplate,
    401                                    &userNotice->derNoticeReference);
    402        if (rv == SECFailure) {
    403            goto loser;
    404        }
    405    }
    406 
    407    return (userNotice);
    408 
    409 loser:
    410    if (arena != NULL) {
    411        PORT_FreeArena(arena, PR_FALSE);
    412    }
    413 
    414    return (NULL);
    415 }
    416 
    417 void
    418 CERT_DestroyUserNotice(CERTUserNotice *userNotice)
    419 {
    420    if (userNotice != NULL) {
    421        PORT_FreeArena(userNotice->arena, PR_FALSE);
    422    }
    423    return;
    424 }
    425 
    426 static CERTPolicyStringCallback policyStringCB = NULL;
    427 static void *policyStringCBArg = NULL;
    428 
    429 void
    430 CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg)
    431 {
    432    policyStringCB = cb;
    433    policyStringCBArg = cbarg;
    434    return;
    435 }
    436 
    437 char *
    438 stringFromUserNotice(SECItem *noticeItem)
    439 {
    440    SECItem *org;
    441    unsigned int len, headerlen;
    442    char *stringbuf;
    443    CERTUserNotice *userNotice;
    444    char *policystr;
    445    char *retstr = NULL;
    446    SECItem *displayText;
    447    SECItem **noticeNumbers;
    448    unsigned int strnum;
    449 
    450    /* decode the user notice */
    451    userNotice = CERT_DecodeUserNotice(noticeItem);
    452    if (userNotice == NULL) {
    453        return (NULL);
    454    }
    455 
    456    org = &userNotice->noticeReference.organization;
    457    if ((org->len != 0) && (policyStringCB != NULL)) {
    458        /* has a noticeReference */
    459 
    460        /* extract the org string */
    461        len = org->len;
    462        stringbuf = (char *)PORT_Alloc(len + 1);
    463        if (stringbuf != NULL) {
    464            PORT_Memcpy(stringbuf, org->data, len);
    465            stringbuf[len] = '\0';
    466 
    467            noticeNumbers = userNotice->noticeReference.noticeNumbers;
    468            while (*noticeNumbers != NULL) {
    469                /* XXX - only one byte integers right now*/
    470                strnum = (*noticeNumbers)->data[0];
    471                policystr =
    472                    (*policyStringCB)(stringbuf, strnum, policyStringCBArg);
    473                if (policystr != NULL) {
    474                    if (retstr != NULL) {
    475                        retstr = PR_sprintf_append(retstr, "\n%s", policystr);
    476                    } else {
    477                        retstr = PR_sprintf_append(retstr, "%s", policystr);
    478                    }
    479 
    480                    PORT_Free(policystr);
    481                }
    482 
    483                noticeNumbers++;
    484            }
    485 
    486            PORT_Free(stringbuf);
    487        }
    488    }
    489 
    490    if (retstr == NULL) {
    491        if (userNotice->displayText.len != 0) {
    492            displayText = &userNotice->displayText;
    493 
    494            if (displayText->len > 2) {
    495                if (displayText->data[0] == SEC_ASN1_VISIBLE_STRING) {
    496                    headerlen = 2;
    497                    if (displayText->data[1] & 0x80) {
    498                        /* multibyte length */
    499                        headerlen += (displayText->data[1] & 0x7f);
    500                    }
    501 
    502                    len = displayText->len - headerlen;
    503                    retstr = (char *)PORT_Alloc(len + 1);
    504                    if (retstr != NULL) {
    505                        PORT_Memcpy(retstr, &displayText->data[headerlen], len);
    506                        retstr[len] = '\0';
    507                    }
    508                }
    509            }
    510        }
    511    }
    512 
    513    CERT_DestroyUserNotice(userNotice);
    514 
    515    return (retstr);
    516 }
    517 
    518 char *
    519 CERT_GetCertCommentString(CERTCertificate *cert)
    520 {
    521    char *retstring = NULL;
    522    SECStatus rv;
    523    SECItem policyItem;
    524    CERTCertificatePolicies *policies = NULL;
    525    CERTPolicyInfo **policyInfos;
    526    CERTPolicyQualifier **policyQualifiers, *qualifier;
    527 
    528    policyItem.data = NULL;
    529 
    530    rv = CERT_FindCertExtension(cert, SEC_OID_X509_CERTIFICATE_POLICIES,
    531                                &policyItem);
    532    if (rv != SECSuccess) {
    533        goto nopolicy;
    534    }
    535 
    536    policies = CERT_DecodeCertificatePoliciesExtension(&policyItem);
    537    if (policies == NULL) {
    538        goto nopolicy;
    539    }
    540 
    541    policyInfos = policies->policyInfos;
    542    /* search through policyInfos looking for the verisign policy */
    543    while (*policyInfos != NULL) {
    544        if ((*policyInfos)->oid == SEC_OID_VERISIGN_USER_NOTICES) {
    545            policyQualifiers = (*policyInfos)->policyQualifiers;
    546            /* search through the policy qualifiers looking for user notice */
    547            while (policyQualifiers != NULL && *policyQualifiers != NULL) {
    548                qualifier = *policyQualifiers;
    549                if (qualifier->oid == SEC_OID_PKIX_USER_NOTICE_QUALIFIER) {
    550                    retstring =
    551                        stringFromUserNotice(&qualifier->qualifierValue);
    552                    break;
    553                }
    554 
    555                policyQualifiers++;
    556            }
    557            break;
    558        }
    559        policyInfos++;
    560    }
    561 
    562 nopolicy:
    563    if (policyItem.data != NULL) {
    564        PORT_Free(policyItem.data);
    565    }
    566 
    567    if (policies != NULL) {
    568        CERT_DestroyCertificatePoliciesExtension(policies);
    569    }
    570 
    571    if (retstring == NULL) {
    572        retstring =
    573            CERT_FindNSStringExtension(cert, SEC_OID_NS_CERT_EXT_COMMENT);
    574    }
    575 
    576    if (retstring != NULL) {
    577        breakLines(retstring);
    578    }
    579 
    580    return (retstring);
    581 }
    582 
    583 const SEC_ASN1Template CERT_OidSeqTemplate[] = {
    584    { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, offsetof(CERTOidSequence, oids),
    585      SEC_ASN1_SUB(SEC_ObjectIDTemplate) }
    586 };
    587 
    588 CERTOidSequence *
    589 CERT_DecodeOidSequence(const SECItem *seqItem)
    590 {
    591    PLArenaPool *arena = NULL;
    592    SECStatus rv;
    593    CERTOidSequence *oidSeq;
    594    SECItem newSeqItem;
    595 
    596    /* make a new arena */
    597    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    598 
    599    if (!arena) {
    600        goto loser;
    601    }
    602 
    603    /* allocate the userNotice structure */
    604    oidSeq =
    605        (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence));
    606 
    607    if (oidSeq == NULL) {
    608        goto loser;
    609    }
    610 
    611    oidSeq->arena = arena;
    612 
    613    /* copy the DER into the arena, since Quick DER returns data that points
    614       into the DER input, which may get freed by the caller */
    615    rv = SECITEM_CopyItem(arena, &newSeqItem, seqItem);
    616    if (rv != SECSuccess) {
    617        goto loser;
    618    }
    619 
    620    /* decode the user notice */
    621    rv =
    622        SEC_QuickDERDecodeItem(arena, oidSeq, CERT_OidSeqTemplate, &newSeqItem);
    623 
    624    if (rv != SECSuccess) {
    625        goto loser;
    626    }
    627 
    628    return (oidSeq);
    629 
    630 loser:
    631    if (arena) {
    632        PORT_FreeArena(arena, PR_FALSE);
    633    }
    634    return (NULL);
    635 }
    636 
    637 void
    638 CERT_DestroyOidSequence(CERTOidSequence *oidSeq)
    639 {
    640    if (oidSeq != NULL) {
    641        PORT_FreeArena(oidSeq->arena, PR_FALSE);
    642    }
    643    return;
    644 }
    645 
    646 PRBool
    647 CERT_GovtApprovedBitSet(CERTCertificate *cert)
    648 {
    649    SECStatus rv;
    650    SECItem extItem;
    651    CERTOidSequence *oidSeq = NULL;
    652    PRBool ret;
    653    SECItem **oids;
    654    SECItem *oid;
    655    SECOidTag oidTag;
    656 
    657    extItem.data = NULL;
    658    rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem);
    659    if (rv != SECSuccess) {
    660        goto loser;
    661    }
    662 
    663    oidSeq = CERT_DecodeOidSequence(&extItem);
    664    if (oidSeq == NULL) {
    665        goto loser;
    666    }
    667 
    668    oids = oidSeq->oids;
    669    while (oids != NULL && *oids != NULL) {
    670        oid = *oids;
    671 
    672        oidTag = SECOID_FindOIDTag(oid);
    673 
    674        if (oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) {
    675            goto success;
    676        }
    677 
    678        oids++;
    679    }
    680 
    681 loser:
    682    ret = PR_FALSE;
    683    goto done;
    684 success:
    685    ret = PR_TRUE;
    686 done:
    687    if (oidSeq != NULL) {
    688        CERT_DestroyOidSequence(oidSeq);
    689    }
    690    if (extItem.data != NULL) {
    691        PORT_Free(extItem.data);
    692    }
    693    return (ret);
    694 }
    695 
    696 SECStatus
    697 CERT_EncodePolicyConstraintsExtension(PLArenaPool *arena,
    698                                      CERTCertificatePolicyConstraints *constr,
    699                                      SECItem *dest)
    700 {
    701    SECStatus rv = SECSuccess;
    702 
    703    PORT_Assert(constr != NULL && dest != NULL);
    704    if (constr == NULL || dest == NULL) {
    705        return SECFailure;
    706    }
    707 
    708    if (SEC_ASN1EncodeItem(arena, dest, constr,
    709                           CERT_PolicyConstraintsTemplate) == NULL) {
    710        rv = SECFailure;
    711    }
    712    return (rv);
    713 }
    714 
    715 SECStatus
    716 CERT_EncodePolicyMappingExtension(PLArenaPool *arena,
    717                                  CERTCertificatePolicyMappings *mapping,
    718                                  SECItem *dest)
    719 {
    720    SECStatus rv = SECSuccess;
    721 
    722    PORT_Assert(mapping != NULL && dest != NULL);
    723    if (mapping == NULL || dest == NULL) {
    724        return SECFailure;
    725    }
    726 
    727    if (SEC_ASN1EncodeItem(arena, dest, mapping, CERT_PolicyMappingsTemplate) ==
    728        NULL) {
    729        rv = SECFailure;
    730    }
    731    return (rv);
    732 }
    733 
    734 SECStatus
    735 CERT_EncodeCertPoliciesExtension(PLArenaPool *arena, CERTPolicyInfo **info,
    736                                 SECItem *dest)
    737 {
    738    SECStatus rv = SECSuccess;
    739 
    740    PORT_Assert(info != NULL && dest != NULL);
    741    if (info == NULL || dest == NULL) {
    742        return SECFailure;
    743    }
    744 
    745    if (SEC_ASN1EncodeItem(arena, dest, info,
    746                           CERT_CertificatePoliciesTemplate) == NULL) {
    747        rv = SECFailure;
    748    }
    749    return (rv);
    750 }
    751 
    752 SECStatus
    753 CERT_EncodeUserNotice(PLArenaPool *arena, CERTUserNotice *notice, SECItem *dest)
    754 {
    755    SECStatus rv = SECSuccess;
    756 
    757    PORT_Assert(notice != NULL && dest != NULL);
    758    if (notice == NULL || dest == NULL) {
    759        return SECFailure;
    760    }
    761 
    762    if (SEC_ASN1EncodeItem(arena, dest, notice, CERT_UserNoticeTemplate) ==
    763        NULL) {
    764        rv = SECFailure;
    765    }
    766 
    767    return (rv);
    768 }
    769 
    770 SECStatus
    771 CERT_EncodeNoticeReference(PLArenaPool *arena, CERTNoticeReference *reference,
    772                           SECItem *dest)
    773 {
    774    SECStatus rv = SECSuccess;
    775 
    776    PORT_Assert(reference != NULL && dest != NULL);
    777    if (reference == NULL || dest == NULL) {
    778        return SECFailure;
    779    }
    780 
    781    if (SEC_ASN1EncodeItem(arena, dest, reference,
    782                           CERT_NoticeReferenceTemplate) == NULL) {
    783        rv = SECFailure;
    784    }
    785 
    786    return (rv);
    787 }
    788 
    789 SECStatus
    790 CERT_EncodeInhibitAnyExtension(PLArenaPool *arena,
    791                               CERTCertificateInhibitAny *certInhibitAny,
    792                               SECItem *dest)
    793 {
    794    SECStatus rv = SECSuccess;
    795 
    796    PORT_Assert(certInhibitAny != NULL && dest != NULL);
    797    if (certInhibitAny == NULL || dest == NULL) {
    798        return SECFailure;
    799    }
    800 
    801    if (SEC_ASN1EncodeItem(arena, dest, certInhibitAny,
    802                           CERT_InhibitAnyTemplate) == NULL) {
    803        rv = SECFailure;
    804    }
    805    return (rv);
    806 }