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