tor-browser

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

xconst.c (7671B)


      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 * X.509 Extension Encoding
      7 */
      8 
      9 #include "prtypes.h"
     10 #include "seccomon.h"
     11 #include "secdert.h"
     12 #include "secoidt.h"
     13 #include "secasn1t.h"
     14 #include "secasn1.h"
     15 #include "cert.h"
     16 #include "secder.h"
     17 #include "prprf.h"
     18 #include "xconst.h"
     19 #include "genname.h"
     20 #include "secasn1.h"
     21 #include "secerr.h"
     22 
     23 static const SEC_ASN1Template CERTSubjectKeyIDTemplate[] = {
     24    { SEC_ASN1_OCTET_STRING }
     25 };
     26 
     27 static const SEC_ASN1Template CERTIA5TypeTemplate[] = {
     28    { SEC_ASN1_IA5_STRING }
     29 };
     30 
     31 SEC_ASN1_MKSUB(SEC_GeneralizedTimeTemplate)
     32 
     33 static const SEC_ASN1Template CERTPrivateKeyUsagePeriodTemplate[] = {
     34    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPrivKeyUsagePeriod) },
     35    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
     36      offsetof(CERTPrivKeyUsagePeriod, notBefore),
     37      SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate) },
     38    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
     39      offsetof(CERTPrivKeyUsagePeriod, notAfter),
     40      SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate) },
     41    { 0 }
     42 };
     43 
     44 const SEC_ASN1Template CERTAltNameTemplate[] = {
     45    { SEC_ASN1_CONSTRUCTED, offsetof(CERTAltNameEncodedContext, encodedGenName),
     46      CERT_GeneralNamesTemplate }
     47 };
     48 
     49 const SEC_ASN1Template CERTAuthInfoAccessItemTemplate[] = {
     50    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTAuthInfoAccess) },
     51    { SEC_ASN1_OBJECT_ID, offsetof(CERTAuthInfoAccess, method) },
     52    { SEC_ASN1_ANY, offsetof(CERTAuthInfoAccess, derLocation) },
     53    { 0 }
     54 };
     55 
     56 const SEC_ASN1Template CERTAuthInfoAccessTemplate[] = {
     57    { SEC_ASN1_SEQUENCE_OF, 0, CERTAuthInfoAccessItemTemplate }
     58 };
     59 
     60 SECStatus
     61 CERT_EncodeSubjectKeyID(PLArenaPool *arena, const SECItem *srcString,
     62                        SECItem *encodedValue)
     63 {
     64    SECStatus rv = SECSuccess;
     65 
     66    if (!srcString) {
     67        PORT_SetError(SEC_ERROR_INVALID_ARGS);
     68        return SECFailure;
     69    }
     70    if (SEC_ASN1EncodeItem(arena, encodedValue, srcString,
     71                           CERTSubjectKeyIDTemplate) == NULL) {
     72        rv = SECFailure;
     73    }
     74 
     75    return (rv);
     76 }
     77 
     78 SECStatus
     79 CERT_EncodePrivateKeyUsagePeriod(PLArenaPool *arena,
     80                                 CERTPrivKeyUsagePeriod *pkup,
     81                                 SECItem *encodedValue)
     82 {
     83    SECStatus rv = SECSuccess;
     84 
     85    if (SEC_ASN1EncodeItem(arena, encodedValue, pkup,
     86                           CERTPrivateKeyUsagePeriodTemplate) == NULL) {
     87        rv = SECFailure;
     88    }
     89    return (rv);
     90 }
     91 
     92 CERTPrivKeyUsagePeriod *
     93 CERT_DecodePrivKeyUsagePeriodExtension(PLArenaPool *arena, SECItem *extnValue)
     94 {
     95    SECStatus rv;
     96    CERTPrivKeyUsagePeriod *pPeriod;
     97    SECItem newExtnValue;
     98 
     99    /* allocate the certificate policies structure */
    100    pPeriod = PORT_ArenaZNew(arena, CERTPrivKeyUsagePeriod);
    101    if (pPeriod == NULL) {
    102        goto loser;
    103    }
    104 
    105    pPeriod->arena = arena;
    106 
    107    /* copy the DER into the arena, since Quick DER returns data that points
    108       into the DER input, which may get freed by the caller */
    109    rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
    110    if (rv != SECSuccess) {
    111        goto loser;
    112    }
    113 
    114    rv = SEC_QuickDERDecodeItem(
    115        arena, pPeriod, CERTPrivateKeyUsagePeriodTemplate, &newExtnValue);
    116    if (rv != SECSuccess) {
    117        goto loser;
    118    }
    119    return pPeriod;
    120 
    121 loser:
    122    return NULL;
    123 }
    124 
    125 SECStatus
    126 CERT_EncodeIA5TypeExtension(PLArenaPool *arena, char *value,
    127                            SECItem *encodedValue)
    128 {
    129    SECItem encodeContext;
    130    SECStatus rv = SECSuccess;
    131 
    132    PORT_Memset(&encodeContext, 0, sizeof(encodeContext));
    133 
    134    if (value != NULL) {
    135        encodeContext.data = (unsigned char *)value;
    136        encodeContext.len = strlen(value);
    137    }
    138    if (SEC_ASN1EncodeItem(arena, encodedValue, &encodeContext,
    139                           CERTIA5TypeTemplate) == NULL) {
    140        rv = SECFailure;
    141    }
    142 
    143    return (rv);
    144 }
    145 
    146 SECStatus
    147 CERT_EncodeAltNameExtension(PLArenaPool *arena, CERTGeneralName *value,
    148                            SECItem *encodedValue)
    149 {
    150    SECItem **encodedGenName;
    151    SECStatus rv = SECSuccess;
    152 
    153    encodedGenName = cert_EncodeGeneralNames(arena, value);
    154    if (SEC_ASN1EncodeItem(arena, encodedValue, &encodedGenName,
    155                           CERT_GeneralNamesTemplate) == NULL) {
    156        rv = SECFailure;
    157    }
    158 
    159    return rv;
    160 }
    161 
    162 CERTGeneralName *
    163 CERT_DecodeAltNameExtension(PLArenaPool *reqArena, SECItem *EncodedAltName)
    164 {
    165    SECStatus rv = SECSuccess;
    166    CERTAltNameEncodedContext encodedContext;
    167    SECItem *newEncodedAltName;
    168 
    169    if (!reqArena) {
    170        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    171        return NULL;
    172    }
    173 
    174    newEncodedAltName = SECITEM_ArenaDupItem(reqArena, EncodedAltName);
    175    if (!newEncodedAltName) {
    176        return NULL;
    177    }
    178 
    179    encodedContext.encodedGenName = NULL;
    180    PORT_Memset(&encodedContext, 0, sizeof(CERTAltNameEncodedContext));
    181    rv = SEC_QuickDERDecodeItem(reqArena, &encodedContext,
    182                                CERT_GeneralNamesTemplate, newEncodedAltName);
    183    if (rv == SECFailure) {
    184        goto loser;
    185    }
    186    if (encodedContext.encodedGenName && encodedContext.encodedGenName[0])
    187        return cert_DecodeGeneralNames(reqArena, encodedContext.encodedGenName);
    188    /* Extension contained an empty GeneralNames sequence */
    189    /* Treat as extension not found */
    190    PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
    191 loser:
    192    return NULL;
    193 }
    194 
    195 SECStatus
    196 CERT_EncodeNameConstraintsExtension(PLArenaPool *arena,
    197                                    CERTNameConstraints *value,
    198                                    SECItem *encodedValue)
    199 {
    200    SECStatus rv = SECSuccess;
    201 
    202    rv = cert_EncodeNameConstraints(value, arena, encodedValue);
    203    return rv;
    204 }
    205 
    206 CERTNameConstraints *
    207 CERT_DecodeNameConstraintsExtension(PLArenaPool *arena,
    208                                    const SECItem *encodedConstraints)
    209 {
    210    return cert_DecodeNameConstraints(arena, encodedConstraints);
    211 }
    212 
    213 CERTAuthInfoAccess **
    214 CERT_DecodeAuthInfoAccessExtension(PLArenaPool *reqArena,
    215                                   const SECItem *encodedExtension)
    216 {
    217    CERTAuthInfoAccess **info = NULL;
    218    SECStatus rv;
    219    int i;
    220    SECItem *newEncodedExtension;
    221 
    222    if (!reqArena) {
    223        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    224        return NULL;
    225    }
    226 
    227    newEncodedExtension = SECITEM_ArenaDupItem(reqArena, encodedExtension);
    228    if (!newEncodedExtension) {
    229        return NULL;
    230    }
    231 
    232    rv = SEC_QuickDERDecodeItem(reqArena, &info, CERTAuthInfoAccessTemplate,
    233                                newEncodedExtension);
    234    if (rv != SECSuccess || info == NULL) {
    235        return NULL;
    236    }
    237 
    238    for (i = 0; info[i] != NULL; i++) {
    239        info[i]->location =
    240            CERT_DecodeGeneralName(reqArena, &(info[i]->derLocation), NULL);
    241    }
    242    return info;
    243 }
    244 
    245 SECStatus
    246 CERT_EncodeInfoAccessExtension(PLArenaPool *arena, CERTAuthInfoAccess **info,
    247                               SECItem *dest)
    248 {
    249    SECItem *dummy;
    250    int i;
    251 
    252    PORT_Assert(info != NULL);
    253    PORT_Assert(dest != NULL);
    254    if (info == NULL || dest == NULL) {
    255        return SECFailure;
    256    }
    257 
    258    for (i = 0; info[i] != NULL; i++) {
    259        if (CERT_EncodeGeneralName(info[i]->location, &(info[i]->derLocation),
    260                                   arena) == NULL)
    261            /* Note that this may leave some of the locations filled in. */
    262            return SECFailure;
    263    }
    264    dummy = SEC_ASN1EncodeItem(arena, dest, &info, CERTAuthInfoAccessTemplate);
    265    if (dummy == NULL) {
    266        return SECFailure;
    267    }
    268    return SECSuccess;
    269 }