Coverage Report

Created: 2024-05-20 06:23

/src/nss/lib/certhigh/xcrldist.c
Line
Count
Source (jump to first uncovered line)
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
 * Code for dealing with x.509 v3 CRL Distribution Point extension.
7
 */
8
#include "genname.h"
9
#include "certt.h"
10
#include "secerr.h"
11
12
SEC_ASN1_MKSUB(SEC_AnyTemplate)
13
SEC_ASN1_MKSUB(SEC_BitStringTemplate)
14
15
extern void PrepareBitStringForEncoding(SECItem *bitMap, SECItem *value);
16
17
static const SEC_ASN1Template FullNameTemplate[] = {
18
    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0,
19
      offsetof(CRLDistributionPoint, derFullName),
20
      CERT_GeneralNamesTemplate }
21
};
22
23
static const SEC_ASN1Template RelativeNameTemplate[] = {
24
    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1,
25
      offsetof(CRLDistributionPoint, distPoint.relativeName),
26
      CERT_RDNTemplate }
27
};
28
29
static const SEC_ASN1Template DistributionPointNameTemplate[] = {
30
    { SEC_ASN1_CHOICE,
31
      offsetof(CRLDistributionPoint, distPointType), NULL,
32
      sizeof(CRLDistributionPoint) },
33
    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0,
34
      offsetof(CRLDistributionPoint, derFullName),
35
      CERT_GeneralNamesTemplate, generalName },
36
    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1,
37
      offsetof(CRLDistributionPoint, distPoint.relativeName),
38
      CERT_RDNTemplate, relativeDistinguishedName },
39
    { 0 }
40
};
41
42
static const SEC_ASN1Template CRLDistributionPointTemplate[] = {
43
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CRLDistributionPoint) },
44
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC |
45
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | SEC_ASN1_XTRN | 0,
46
      offsetof(CRLDistributionPoint, derDistPoint),
47
      SEC_ASN1_SUB(SEC_AnyTemplate) },
48
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
49
      offsetof(CRLDistributionPoint, bitsmap),
50
      SEC_ASN1_SUB(SEC_BitStringTemplate) },
51
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC |
52
          SEC_ASN1_CONSTRUCTED | 2,
53
      offsetof(CRLDistributionPoint, derCrlIssuer),
54
      CERT_GeneralNamesTemplate },
55
    { 0 }
56
};
57
58
const SEC_ASN1Template CERTCRLDistributionPointsTemplate[] = {
59
    { SEC_ASN1_SEQUENCE_OF, 0, CRLDistributionPointTemplate }
60
};
61
62
SECStatus
63
CERT_EncodeCRLDistributionPoints(PLArenaPool *arena,
64
                                 CERTCrlDistributionPoints *value,
65
                                 SECItem *derValue)
66
0
{
67
0
    CRLDistributionPoint **pointList, *point;
68
0
    PLArenaPool *ourPool = NULL;
69
0
    SECStatus rv = SECSuccess;
70
71
0
    PORT_Assert(derValue);
72
0
    PORT_Assert(value && value->distPoints);
73
74
0
    do {
75
0
        ourPool = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
76
0
        if (ourPool == NULL) {
77
0
            rv = SECFailure;
78
0
            break;
79
0
        }
80
81
0
        pointList = value->distPoints;
82
0
        while (*pointList) {
83
0
            point = *pointList;
84
0
            point->derFullName = NULL;
85
0
            point->derDistPoint.data = NULL;
86
87
0
            switch (point->distPointType) {
88
0
                case generalName:
89
0
                    point->derFullName = cert_EncodeGeneralNames(ourPool, point->distPoint.fullName);
90
91
0
                    if (!point->derFullName ||
92
0
                        !SEC_ASN1EncodeItem(ourPool, &point->derDistPoint,
93
0
                                            point, FullNameTemplate))
94
0
                        rv = SECFailure;
95
0
                    break;
96
97
0
                case relativeDistinguishedName:
98
0
                    if (!SEC_ASN1EncodeItem(ourPool, &point->derDistPoint,
99
0
                                            point, RelativeNameTemplate))
100
0
                        rv = SECFailure;
101
0
                    break;
102
103
0
                default:
104
0
                    PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
105
0
                    rv = SECFailure;
106
0
                    break;
107
0
            }
108
109
0
            if (rv != SECSuccess)
110
0
                break;
111
112
0
            if (point->reasons.data)
113
0
                PrepareBitStringForEncoding(&point->bitsmap, &point->reasons);
114
115
0
            if (point->crlIssuer) {
116
0
                point->derCrlIssuer = cert_EncodeGeneralNames(ourPool, point->crlIssuer);
117
0
                if (!point->derCrlIssuer) {
118
0
                    rv = SECFailure;
119
0
                    break;
120
0
                }
121
0
            }
122
0
            ++pointList;
123
0
        }
124
0
        if (rv != SECSuccess)
125
0
            break;
126
0
        if (!SEC_ASN1EncodeItem(arena, derValue, value,
127
0
                                CERTCRLDistributionPointsTemplate)) {
128
0
            rv = SECFailure;
129
0
            break;
130
0
        }
131
0
    } while (0);
132
0
    PORT_FreeArena(ourPool, PR_FALSE);
133
0
    return rv;
134
0
}
135
136
CERTCrlDistributionPoints *
137
CERT_DecodeCRLDistributionPoints(PLArenaPool *arena, SECItem *encodedValue)
138
0
{
139
0
    CERTCrlDistributionPoints *value = NULL;
140
0
    CRLDistributionPoint **pointList, *point;
141
0
    SECStatus rv = SECSuccess;
142
0
    SECItem newEncodedValue;
143
144
0
    PORT_Assert(arena);
145
0
    do {
146
0
        value = PORT_ArenaZNew(arena, CERTCrlDistributionPoints);
147
0
        if (value == NULL) {
148
0
            rv = SECFailure;
149
0
            break;
150
0
        }
151
152
        /* copy the DER into the arena, since Quick DER returns data that points
153
           into the DER input, which may get freed by the caller */
154
0
        rv = SECITEM_CopyItem(arena, &newEncodedValue, encodedValue);
155
0
        if (rv != SECSuccess)
156
0
            break;
157
158
0
        rv = SEC_QuickDERDecodeItem(arena, &value->distPoints,
159
0
                                    CERTCRLDistributionPointsTemplate, &newEncodedValue);
160
0
        if (rv != SECSuccess)
161
0
            break;
162
163
0
        pointList = value->distPoints;
164
0
        while (NULL != (point = *pointList)) {
165
166
            /* get the data if the distributionPointName is not omitted */
167
0
            if (point->derDistPoint.data != NULL) {
168
0
                rv = SEC_QuickDERDecodeItem(arena, point,
169
0
                                            DistributionPointNameTemplate, &(point->derDistPoint));
170
0
                if (rv != SECSuccess)
171
0
                    break;
172
173
0
                switch (point->distPointType) {
174
0
                    case generalName:
175
0
                        point->distPoint.fullName =
176
0
                            cert_DecodeGeneralNames(arena, point->derFullName);
177
0
                        rv = point->distPoint.fullName ? SECSuccess : SECFailure;
178
0
                        break;
179
180
0
                    case relativeDistinguishedName:
181
0
                        break;
182
183
0
                    default:
184
0
                        PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
185
0
                        rv = SECFailure;
186
0
                        break;
187
0
                } /* end switch */
188
0
                if (rv != SECSuccess)
189
0
                    break;
190
0
            } /* end if */
191
192
            /* Get the reason code if it's not omitted in the encoding */
193
0
            if (point->bitsmap.data != NULL) {
194
0
                SECItem bitsmap = point->bitsmap;
195
0
                DER_ConvertBitString(&bitsmap);
196
0
                rv = SECITEM_CopyItem(arena, &point->reasons, &bitsmap);
197
0
                if (rv != SECSuccess)
198
0
                    break;
199
0
            }
200
201
            /* Get the crl issuer name if it's not omitted in the encoding */
202
0
            if (point->derCrlIssuer != NULL) {
203
0
                point->crlIssuer = cert_DecodeGeneralNames(arena,
204
0
                                                           point->derCrlIssuer);
205
0
                if (!point->crlIssuer)
206
0
                    break;
207
0
            }
208
0
            ++pointList;
209
0
        } /* end while points remain */
210
0
    } while (0);
211
0
    return (rv == SECSuccess ? value : NULL);
212
0
}