Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/certdb/certv3.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 X509.V3 extensions. | |
7 */ | |
8 | |
9 #include "cert.h" | |
10 #include "secitem.h" | |
11 #include "secoid.h" | |
12 #include "secder.h" | |
13 #include "secasn1.h" | |
14 #include "certxutl.h" | |
15 #include "secerr.h" | |
16 | |
17 SECStatus | |
18 CERT_FindCertExtensionByOID(CERTCertificate *cert, SECItem *oid, | |
19 SECItem *value) | |
20 { | |
21 return (cert_FindExtensionByOID (cert->extensions, oid, value)); | |
22 } | |
23 | |
24 | |
25 SECStatus | |
26 CERT_FindCertExtension(const CERTCertificate *cert, int tag, SECItem *value) | |
27 { | |
28 return (cert_FindExtension (cert->extensions, tag, value)); | |
29 } | |
30 | |
31 static void | |
32 SetExts(void *object, CERTCertExtension **exts) | |
33 { | |
34 CERTCertificate *cert = (CERTCertificate *)object; | |
35 | |
36 cert->extensions = exts; | |
37 DER_SetUInteger (cert->arena, &(cert->version), SEC_CERTIFICATE_VERSION_3); | |
38 } | |
39 | |
40 void * | |
41 CERT_StartCertExtensions(CERTCertificate *cert) | |
42 { | |
43 return (cert_StartExtensions ((void *)cert, cert->arena, SetExts)); | |
44 } | |
45 | |
46 /* find the given extension in the certificate of the Issuer of 'cert' */ | |
47 SECStatus | |
48 CERT_FindIssuerCertExtension(CERTCertificate *cert, int tag, SECItem *value) | |
49 { | |
50 CERTCertificate *issuercert; | |
51 SECStatus rv; | |
52 | |
53 issuercert = CERT_FindCertByName(cert->dbhandle, &cert->derIssuer); | |
54 if ( issuercert ) { | |
55 rv = cert_FindExtension(issuercert->extensions, tag, value); | |
56 CERT_DestroyCertificate(issuercert); | |
57 } else { | |
58 rv = SECFailure; | |
59 } | |
60 | |
61 return(rv); | |
62 } | |
63 | |
64 /* find a URL extension in the cert or its CA | |
65 * apply the base URL string if it exists | |
66 */ | |
67 char * | |
68 CERT_FindCertURLExtension(CERTCertificate *cert, int tag, int catag) | |
69 { | |
70 SECStatus rv; | |
71 SECItem urlitem = {siBuffer,0}; | |
72 SECItem baseitem = {siBuffer,0}; | |
73 SECItem urlstringitem = {siBuffer,0}; | |
74 SECItem basestringitem = {siBuffer,0}; | |
75 PLArenaPool *arena = NULL; | |
76 PRBool hasbase; | |
77 char *urlstring; | |
78 char *str; | |
79 int len; | |
80 unsigned int i; | |
81 | |
82 urlstring = NULL; | |
83 | |
84 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
85 if ( ! arena ) { | |
86 goto loser; | |
87 } | |
88 | |
89 hasbase = PR_FALSE; | |
90 | |
91 rv = cert_FindExtension(cert->extensions, tag, &urlitem); | |
92 if ( rv == SECSuccess ) { | |
93 rv = cert_FindExtension(cert->extensions, SEC_OID_NS_CERT_EXT_BASE_URL, | |
94 &baseitem); | |
95 if ( rv == SECSuccess ) { | |
96 hasbase = PR_TRUE; | |
97 } | |
98 | |
99 } else if ( catag ) { | |
100 /* if the cert doesn't have the extensions, see if the issuer does */ | |
101 rv = CERT_FindIssuerCertExtension(cert, catag, &urlitem); | |
102 if ( rv != SECSuccess ) { | |
103 goto loser; | |
104 } | |
105 rv = CERT_FindIssuerCertExtension(cert, SEC_OID_NS_CERT_EXT_BASE_URL, | |
106 &baseitem); | |
107 if ( rv == SECSuccess ) { | |
108 hasbase = PR_TRUE; | |
109 } | |
110 } else { | |
111 goto loser; | |
112 } | |
113 | |
114 rv = SEC_QuickDERDecodeItem(arena, &urlstringitem, | |
115 SEC_ASN1_GET(SEC_IA5StringTemplate), &urlitem); | |
116 | |
117 if ( rv != SECSuccess ) { | |
118 goto loser; | |
119 } | |
120 if ( hasbase ) { | |
121 rv = SEC_QuickDERDecodeItem(arena, &basestringitem, | |
122 SEC_ASN1_GET(SEC_IA5StringTemplate), | |
123 &baseitem); | |
124 | |
125 if ( rv != SECSuccess ) { | |
126 goto loser; | |
127 } | |
128 } | |
129 | |
130 len = urlstringitem.len + ( hasbase ? basestringitem.len : 0 ) + 1; | |
131 | |
132 str = urlstring = (char *)PORT_Alloc(len); | |
133 if ( urlstring == NULL ) { | |
134 goto loser; | |
135 } | |
136 | |
137 /* copy the URL base first */ | |
138 if ( hasbase ) { | |
139 | |
140 /* if the urlstring has a : in it, then we assume it is an absolute | |
141 * URL, and will not get the base string pre-pended | |
142 */ | |
143 for ( i = 0; i < urlstringitem.len; i++ ) { | |
144 if ( urlstringitem.data[i] == ':' ) { | |
145 goto nobase; | |
146 } | |
147 } | |
148 | |
149 PORT_Memcpy(str, basestringitem.data, basestringitem.len); | |
150 str += basestringitem.len; | |
151 | |
152 } | |
153 | |
154 nobase: | |
155 /* copy the rest (or all) of the URL */ | |
156 PORT_Memcpy(str, urlstringitem.data, urlstringitem.len); | |
157 str += urlstringitem.len; | |
158 | |
159 *str = '\0'; | |
160 goto done; | |
161 | |
162 loser: | |
163 if ( urlstring ) { | |
164 PORT_Free(urlstring); | |
165 } | |
166 | |
167 urlstring = NULL; | |
168 done: | |
169 if ( arena ) { | |
170 PORT_FreeArena(arena, PR_FALSE); | |
171 } | |
172 if ( baseitem.data ) { | |
173 PORT_Free(baseitem.data); | |
174 } | |
175 if ( urlitem.data ) { | |
176 PORT_Free(urlitem.data); | |
177 } | |
178 | |
179 return(urlstring); | |
180 } | |
181 | |
182 /* | |
183 * get the value of the Netscape Certificate Type Extension | |
184 */ | |
185 SECStatus | |
186 CERT_FindNSCertTypeExtension(CERTCertificate *cert, SECItem *retItem) | |
187 { | |
188 | |
189 return (CERT_FindBitStringExtension | |
190 (cert->extensions, SEC_OID_NS_CERT_EXT_CERT_TYPE, retItem)); | |
191 } | |
192 | |
193 | |
194 /* | |
195 * get the value of a string type extension | |
196 */ | |
197 char * | |
198 CERT_FindNSStringExtension(CERTCertificate *cert, int oidtag) | |
199 { | |
200 SECItem wrapperItem, tmpItem = {siBuffer,0}; | |
201 SECStatus rv; | |
202 PLArenaPool *arena = NULL; | |
203 char *retstring = NULL; | |
204 | |
205 wrapperItem.data = NULL; | |
206 tmpItem.data = NULL; | |
207 | |
208 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
209 | |
210 if ( ! arena ) { | |
211 goto loser; | |
212 } | |
213 | |
214 rv = cert_FindExtension(cert->extensions, oidtag, | |
215 &wrapperItem); | |
216 if ( rv != SECSuccess ) { | |
217 goto loser; | |
218 } | |
219 | |
220 rv = SEC_QuickDERDecodeItem(arena, &tmpItem, | |
221 SEC_ASN1_GET(SEC_IA5StringTemplate), &wrapperItem); | |
222 | |
223 if ( rv != SECSuccess ) { | |
224 goto loser; | |
225 } | |
226 | |
227 retstring = (char *)PORT_Alloc(tmpItem.len + 1 ); | |
228 if ( retstring == NULL ) { | |
229 goto loser; | |
230 } | |
231 | |
232 PORT_Memcpy(retstring, tmpItem.data, tmpItem.len); | |
233 retstring[tmpItem.len] = '\0'; | |
234 | |
235 loser: | |
236 if ( arena ) { | |
237 PORT_FreeArena(arena, PR_FALSE); | |
238 } | |
239 | |
240 if ( wrapperItem.data ) { | |
241 PORT_Free(wrapperItem.data); | |
242 } | |
243 | |
244 return(retstring); | |
245 } | |
246 | |
247 /* | |
248 * get the value of the X.509 v3 Key Usage Extension | |
249 */ | |
250 SECStatus | |
251 CERT_FindKeyUsageExtension(CERTCertificate *cert, SECItem *retItem) | |
252 { | |
253 | |
254 return (CERT_FindBitStringExtension(cert->extensions, | |
255 SEC_OID_X509_KEY_USAGE, retItem)); | |
256 } | |
257 | |
258 /* | |
259 * get the value of the X.509 v3 Key Usage Extension | |
260 */ | |
261 SECStatus | |
262 CERT_FindSubjectKeyIDExtension(CERTCertificate *cert, SECItem *retItem) | |
263 { | |
264 | |
265 SECStatus rv; | |
266 SECItem encodedValue = {siBuffer, NULL, 0 }; | |
267 SECItem decodedValue = {siBuffer, NULL, 0 }; | |
268 | |
269 rv = cert_FindExtension | |
270 (cert->extensions, SEC_OID_X509_SUBJECT_KEY_ID, &encodedValue); | |
271 if (rv == SECSuccess) { | |
272 PLArenaPool * tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
273 if (tmpArena) { | |
274 rv = SEC_QuickDERDecodeItem(tmpArena, &decodedValue, | |
275 SEC_ASN1_GET(SEC_OctetStringTemplate), | |
276 &encodedValue); | |
277 if (rv == SECSuccess) { | |
278 rv = SECITEM_CopyItem(NULL, retItem, &decodedValue); | |
279 } | |
280 PORT_FreeArena(tmpArena, PR_FALSE); | |
281 } else { | |
282 rv = SECFailure; | |
283 } | |
284 } | |
285 SECITEM_FreeItem(&encodedValue, PR_FALSE); | |
286 return rv; | |
287 } | |
288 | |
289 SECStatus | |
290 CERT_FindBasicConstraintExten(CERTCertificate *cert, | |
291 CERTBasicConstraints *value) | |
292 { | |
293 SECItem encodedExtenValue; | |
294 SECStatus rv; | |
295 | |
296 encodedExtenValue.data = NULL; | |
297 encodedExtenValue.len = 0; | |
298 | |
299 rv = cert_FindExtension(cert->extensions, SEC_OID_X509_BASIC_CONSTRAINTS, | |
300 &encodedExtenValue); | |
301 if ( rv != SECSuccess ) { | |
302 return (rv); | |
303 } | |
304 | |
305 rv = CERT_DecodeBasicConstraintValue (value, &encodedExtenValue); | |
306 | |
307 /* free the raw extension data */ | |
308 PORT_Free(encodedExtenValue.data); | |
309 encodedExtenValue.data = NULL; | |
310 | |
311 return(rv); | |
312 } | |
313 | |
314 CERTAuthKeyID * | |
315 CERT_FindAuthKeyIDExten (PLArenaPool *arena, CERTCertificate *cert) | |
316 { | |
317 SECItem encodedExtenValue; | |
318 SECStatus rv; | |
319 CERTAuthKeyID *ret; | |
320 | |
321 encodedExtenValue.data = NULL; | |
322 encodedExtenValue.len = 0; | |
323 | |
324 rv = cert_FindExtension(cert->extensions, SEC_OID_X509_AUTH_KEY_ID, | |
325 &encodedExtenValue); | |
326 if ( rv != SECSuccess ) { | |
327 return (NULL); | |
328 } | |
329 | |
330 ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue); | |
331 | |
332 PORT_Free(encodedExtenValue.data); | |
333 encodedExtenValue.data = NULL; | |
334 | |
335 return(ret); | |
336 } | |
337 | |
338 SECStatus | |
339 CERT_CheckCertUsage(CERTCertificate *cert, unsigned char usage) | |
340 { | |
341 SECItem keyUsage; | |
342 SECStatus rv; | |
343 | |
344 /* There is no extension, v1 or v2 certificate */ | |
345 if (cert->extensions == NULL) { | |
346 return (SECSuccess); | |
347 } | |
348 | |
349 keyUsage.data = NULL; | |
350 | |
351 /* This code formerly ignored the Key Usage extension if it was | |
352 ** marked non-critical. That was wrong. Since we do understand it, | |
353 ** we are obligated to honor it, whether or not it is critical. | |
354 */ | |
355 rv = CERT_FindKeyUsageExtension(cert, &keyUsage); | |
356 if (rv == SECFailure) { | |
357 rv = (PORT_GetError () == SEC_ERROR_EXTENSION_NOT_FOUND) ? | |
358 SECSuccess : SECFailure; | |
359 } else if (!(keyUsage.data[0] & usage)) { | |
360 PORT_SetError (SEC_ERROR_CERT_USAGES_INVALID); | |
361 rv = SECFailure; | |
362 } | |
363 PORT_Free (keyUsage.data); | |
364 return (rv); | |
365 } |