/src/nss-nspr/nss/lib/certdb/xconst.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 | | * 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 | 0 | { |
64 | 0 | SECStatus rv = SECSuccess; |
65 | |
|
66 | 0 | if (!srcString) { |
67 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
68 | 0 | return SECFailure; |
69 | 0 | } |
70 | 0 | if (SEC_ASN1EncodeItem(arena, encodedValue, srcString, |
71 | 0 | CERTSubjectKeyIDTemplate) == NULL) { |
72 | 0 | rv = SECFailure; |
73 | 0 | } |
74 | |
|
75 | 0 | return (rv); |
76 | 0 | } |
77 | | |
78 | | SECStatus |
79 | | CERT_EncodePrivateKeyUsagePeriod(PLArenaPool *arena, |
80 | | CERTPrivKeyUsagePeriod *pkup, |
81 | | SECItem *encodedValue) |
82 | 0 | { |
83 | 0 | SECStatus rv = SECSuccess; |
84 | |
|
85 | 0 | if (SEC_ASN1EncodeItem(arena, encodedValue, pkup, |
86 | 0 | CERTPrivateKeyUsagePeriodTemplate) == NULL) { |
87 | 0 | rv = SECFailure; |
88 | 0 | } |
89 | 0 | return (rv); |
90 | 0 | } |
91 | | |
92 | | CERTPrivKeyUsagePeriod * |
93 | | CERT_DecodePrivKeyUsagePeriodExtension(PLArenaPool *arena, SECItem *extnValue) |
94 | 0 | { |
95 | 0 | SECStatus rv; |
96 | 0 | CERTPrivKeyUsagePeriod *pPeriod; |
97 | 0 | SECItem newExtnValue; |
98 | | |
99 | | /* allocate the certificate policies structure */ |
100 | 0 | pPeriod = PORT_ArenaZNew(arena, CERTPrivKeyUsagePeriod); |
101 | 0 | if (pPeriod == NULL) { |
102 | 0 | goto loser; |
103 | 0 | } |
104 | | |
105 | 0 | 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 | 0 | rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue); |
110 | 0 | if (rv != SECSuccess) { |
111 | 0 | goto loser; |
112 | 0 | } |
113 | | |
114 | 0 | rv = SEC_QuickDERDecodeItem( |
115 | 0 | arena, pPeriod, CERTPrivateKeyUsagePeriodTemplate, &newExtnValue); |
116 | 0 | if (rv != SECSuccess) { |
117 | 0 | goto loser; |
118 | 0 | } |
119 | 0 | return pPeriod; |
120 | | |
121 | 0 | loser: |
122 | 0 | return NULL; |
123 | 0 | } |
124 | | |
125 | | SECStatus |
126 | | CERT_EncodeIA5TypeExtension(PLArenaPool *arena, char *value, |
127 | | SECItem *encodedValue) |
128 | 0 | { |
129 | 0 | SECItem encodeContext; |
130 | 0 | SECStatus rv = SECSuccess; |
131 | |
|
132 | 0 | PORT_Memset(&encodeContext, 0, sizeof(encodeContext)); |
133 | |
|
134 | 0 | if (value != NULL) { |
135 | 0 | encodeContext.data = (unsigned char *)value; |
136 | 0 | encodeContext.len = strlen(value); |
137 | 0 | } |
138 | 0 | if (SEC_ASN1EncodeItem(arena, encodedValue, &encodeContext, |
139 | 0 | CERTIA5TypeTemplate) == NULL) { |
140 | 0 | rv = SECFailure; |
141 | 0 | } |
142 | |
|
143 | 0 | return (rv); |
144 | 0 | } |
145 | | |
146 | | SECStatus |
147 | | CERT_EncodeAltNameExtension(PLArenaPool *arena, CERTGeneralName *value, |
148 | | SECItem *encodedValue) |
149 | 0 | { |
150 | 0 | SECItem **encodedGenName; |
151 | 0 | SECStatus rv = SECSuccess; |
152 | |
|
153 | 0 | encodedGenName = cert_EncodeGeneralNames(arena, value); |
154 | 0 | if (SEC_ASN1EncodeItem(arena, encodedValue, &encodedGenName, |
155 | 0 | CERT_GeneralNamesTemplate) == NULL) { |
156 | 0 | rv = SECFailure; |
157 | 0 | } |
158 | |
|
159 | 0 | return rv; |
160 | 0 | } |
161 | | |
162 | | CERTGeneralName * |
163 | | CERT_DecodeAltNameExtension(PLArenaPool *reqArena, SECItem *EncodedAltName) |
164 | 0 | { |
165 | 0 | SECStatus rv = SECSuccess; |
166 | 0 | CERTAltNameEncodedContext encodedContext; |
167 | 0 | SECItem *newEncodedAltName; |
168 | |
|
169 | 0 | if (!reqArena) { |
170 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
171 | 0 | return NULL; |
172 | 0 | } |
173 | | |
174 | 0 | newEncodedAltName = SECITEM_ArenaDupItem(reqArena, EncodedAltName); |
175 | 0 | if (!newEncodedAltName) { |
176 | 0 | return NULL; |
177 | 0 | } |
178 | | |
179 | 0 | encodedContext.encodedGenName = NULL; |
180 | 0 | PORT_Memset(&encodedContext, 0, sizeof(CERTAltNameEncodedContext)); |
181 | 0 | rv = SEC_QuickDERDecodeItem(reqArena, &encodedContext, |
182 | 0 | CERT_GeneralNamesTemplate, newEncodedAltName); |
183 | 0 | if (rv == SECFailure) { |
184 | 0 | goto loser; |
185 | 0 | } |
186 | 0 | if (encodedContext.encodedGenName && encodedContext.encodedGenName[0]) |
187 | 0 | return cert_DecodeGeneralNames(reqArena, encodedContext.encodedGenName); |
188 | | /* Extension contained an empty GeneralNames sequence */ |
189 | | /* Treat as extension not found */ |
190 | 0 | PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND); |
191 | 0 | loser: |
192 | 0 | return NULL; |
193 | 0 | } |
194 | | |
195 | | SECStatus |
196 | | CERT_EncodeNameConstraintsExtension(PLArenaPool *arena, |
197 | | CERTNameConstraints *value, |
198 | | SECItem *encodedValue) |
199 | 0 | { |
200 | 0 | SECStatus rv = SECSuccess; |
201 | |
|
202 | 0 | rv = cert_EncodeNameConstraints(value, arena, encodedValue); |
203 | 0 | return rv; |
204 | 0 | } |
205 | | |
206 | | CERTNameConstraints * |
207 | | CERT_DecodeNameConstraintsExtension(PLArenaPool *arena, |
208 | | const SECItem *encodedConstraints) |
209 | 0 | { |
210 | 0 | return cert_DecodeNameConstraints(arena, encodedConstraints); |
211 | 0 | } |
212 | | |
213 | | CERTAuthInfoAccess ** |
214 | | CERT_DecodeAuthInfoAccessExtension(PLArenaPool *reqArena, |
215 | | const SECItem *encodedExtension) |
216 | 0 | { |
217 | 0 | CERTAuthInfoAccess **info = NULL; |
218 | 0 | SECStatus rv; |
219 | 0 | int i; |
220 | 0 | SECItem *newEncodedExtension; |
221 | |
|
222 | 0 | if (!reqArena) { |
223 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
224 | 0 | return NULL; |
225 | 0 | } |
226 | | |
227 | 0 | newEncodedExtension = SECITEM_ArenaDupItem(reqArena, encodedExtension); |
228 | 0 | if (!newEncodedExtension) { |
229 | 0 | return NULL; |
230 | 0 | } |
231 | | |
232 | 0 | rv = SEC_QuickDERDecodeItem(reqArena, &info, CERTAuthInfoAccessTemplate, |
233 | 0 | newEncodedExtension); |
234 | 0 | if (rv != SECSuccess || info == NULL) { |
235 | 0 | return NULL; |
236 | 0 | } |
237 | | |
238 | 0 | for (i = 0; info[i] != NULL; i++) { |
239 | 0 | info[i]->location = |
240 | 0 | CERT_DecodeGeneralName(reqArena, &(info[i]->derLocation), NULL); |
241 | 0 | } |
242 | 0 | return info; |
243 | 0 | } |
244 | | |
245 | | SECStatus |
246 | | CERT_EncodeInfoAccessExtension(PLArenaPool *arena, CERTAuthInfoAccess **info, |
247 | | SECItem *dest) |
248 | 0 | { |
249 | 0 | SECItem *dummy; |
250 | 0 | int i; |
251 | |
|
252 | 0 | PORT_Assert(info != NULL); |
253 | 0 | PORT_Assert(dest != NULL); |
254 | 0 | if (info == NULL || dest == NULL) { |
255 | 0 | return SECFailure; |
256 | 0 | } |
257 | | |
258 | 0 | for (i = 0; info[i] != NULL; i++) { |
259 | 0 | if (CERT_EncodeGeneralName(info[i]->location, &(info[i]->derLocation), |
260 | 0 | arena) == NULL) |
261 | | /* Note that this may leave some of the locations filled in. */ |
262 | 0 | return SECFailure; |
263 | 0 | } |
264 | 0 | dummy = SEC_ASN1EncodeItem(arena, dest, &info, CERTAuthInfoAccessTemplate); |
265 | 0 | if (dummy == NULL) { |
266 | 0 | return SECFailure; |
267 | 0 | } |
268 | 0 | return SECSuccess; |
269 | 0 | } |