OLD | NEW |
| (Empty) |
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 { | |
67 CRLDistributionPoint **pointList, *point; | |
68 PLArenaPool *ourPool = NULL; | |
69 SECStatus rv = SECSuccess; | |
70 | |
71 PORT_Assert(derValue); | |
72 PORT_Assert(value && value->distPoints); | |
73 | |
74 do { | |
75 ourPool = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
76 if (ourPool == NULL) { | |
77 rv = SECFailure; | |
78 break; | |
79 } | |
80 | |
81 pointList = value->distPoints; | |
82 while (*pointList) { | |
83 point = *pointList; | |
84 point->derFullName = NULL; | |
85 point->derDistPoint.data = NULL; | |
86 | |
87 switch (point->distPointType) { | |
88 case generalName: | |
89 point->derFullName = cert_EncodeGeneralNames(ourPool, point-
>distPoint.fullName); | |
90 | |
91 if (!point->derFullName || | |
92 !SEC_ASN1EncodeItem(ourPool, &point->derDistPoint, | |
93 point, FullNameTemplate)) | |
94 rv = SECFailure; | |
95 break; | |
96 | |
97 case relativeDistinguishedName: | |
98 if (!SEC_ASN1EncodeItem(ourPool, &point->derDistPoint, | |
99 point, RelativeNameTemplate)) | |
100 rv = SECFailure; | |
101 break; | |
102 | |
103 default: | |
104 PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID); | |
105 rv = SECFailure; | |
106 break; | |
107 } | |
108 | |
109 if (rv != SECSuccess) | |
110 break; | |
111 | |
112 if (point->reasons.data) | |
113 PrepareBitStringForEncoding(&point->bitsmap, &point->reasons); | |
114 | |
115 if (point->crlIssuer) { | |
116 point->derCrlIssuer = cert_EncodeGeneralNames(ourPool, point->cr
lIssuer); | |
117 if (!point->derCrlIssuer) { | |
118 rv = SECFailure; | |
119 break; | |
120 } | |
121 } | |
122 ++pointList; | |
123 } | |
124 if (rv != SECSuccess) | |
125 break; | |
126 if (!SEC_ASN1EncodeItem(arena, derValue, value, | |
127 CERTCRLDistributionPointsTemplate)) { | |
128 rv = SECFailure; | |
129 break; | |
130 } | |
131 } while (0); | |
132 PORT_FreeArena(ourPool, PR_FALSE); | |
133 return rv; | |
134 } | |
135 | |
136 CERTCrlDistributionPoints * | |
137 CERT_DecodeCRLDistributionPoints(PLArenaPool *arena, SECItem *encodedValue) | |
138 { | |
139 CERTCrlDistributionPoints *value = NULL; | |
140 CRLDistributionPoint **pointList, *point; | |
141 SECStatus rv = SECSuccess; | |
142 SECItem newEncodedValue; | |
143 | |
144 PORT_Assert(arena); | |
145 do { | |
146 value = PORT_ArenaZNew(arena, CERTCrlDistributionPoints); | |
147 if (value == NULL) { | |
148 rv = SECFailure; | |
149 break; | |
150 } | |
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 rv = SECITEM_CopyItem(arena, &newEncodedValue, encodedValue); | |
155 if (rv != SECSuccess) | |
156 break; | |
157 | |
158 rv = SEC_QuickDERDecodeItem(arena, &value->distPoints, | |
159 CERTCRLDistributionPointsTemplate, &newEncod
edValue); | |
160 if (rv != SECSuccess) | |
161 break; | |
162 | |
163 pointList = value->distPoints; | |
164 while (NULL != (point = *pointList)) { | |
165 | |
166 /* get the data if the distributionPointName is not omitted */ | |
167 if (point->derDistPoint.data != NULL) { | |
168 rv = SEC_QuickDERDecodeItem(arena, point, | |
169 DistributionPointNameTemplate, &(poi
nt->derDistPoint)); | |
170 if (rv != SECSuccess) | |
171 break; | |
172 | |
173 switch (point->distPointType) { | |
174 case generalName: | |
175 point->distPoint.fullName = | |
176 cert_DecodeGeneralNames(arena, point->derFullName); | |
177 rv = point->distPoint.fullName ? SECSuccess : SECFailure
; | |
178 break; | |
179 | |
180 case relativeDistinguishedName: | |
181 break; | |
182 | |
183 default: | |
184 PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID); | |
185 rv = SECFailure; | |
186 break; | |
187 } /* end switch */ | |
188 if (rv != SECSuccess) | |
189 break; | |
190 } /* end if */ | |
191 | |
192 /* Get the reason code if it's not omitted in the encoding */ | |
193 if (point->bitsmap.data != NULL) { | |
194 SECItem bitsmap = point->bitsmap; | |
195 DER_ConvertBitString(&bitsmap); | |
196 rv = SECITEM_CopyItem(arena, &point->reasons, &bitsmap); | |
197 if (rv != SECSuccess) | |
198 break; | |
199 } | |
200 | |
201 /* Get the crl issuer name if it's not omitted in the encoding */ | |
202 if (point->derCrlIssuer != NULL) { | |
203 point->crlIssuer = cert_DecodeGeneralNames(arena, | |
204 point->derCrlIssuer); | |
205 if (!point->crlIssuer) | |
206 break; | |
207 } | |
208 ++pointList; | |
209 } /* end while points remain */ | |
210 } while (0); | |
211 return (rv == SECSuccess ? value : NULL); | |
212 } | |
OLD | NEW |