comparison nss/lib/certdb/certxutl.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 * Certificate Extensions handling code
7 *
8 */
9
10 #include "cert.h"
11 #include "secitem.h"
12 #include "secoid.h"
13 #include "secder.h"
14 #include "secasn1.h"
15 #include "certxutl.h"
16 #include "secerr.h"
17
18 #ifdef OLD
19 #include "ocspti.h" /* XXX a better extensions interface would not
20 * require knowledge of data structures of callers */
21 #endif
22
23 static CERTCertExtension *
24 GetExtension (CERTCertExtension **extensions, SECItem *oid)
25 {
26 CERTCertExtension **exts;
27 CERTCertExtension *ext = NULL;
28 SECComparison comp;
29
30 exts = extensions;
31
32 if (exts) {
33 while ( *exts ) {
34 ext = *exts;
35 comp = SECITEM_CompareItem(oid, &ext->id);
36 if ( comp == SECEqual )
37 break;
38
39 exts++;
40 }
41 return (*exts ? ext : NULL);
42 }
43 return (NULL);
44 }
45
46 SECStatus
47 cert_FindExtensionByOID (CERTCertExtension **extensions, SECItem *oid, SECItem *value)
48 {
49 CERTCertExtension *ext;
50 SECStatus rv = SECSuccess;
51
52 ext = GetExtension (extensions, oid);
53 if (ext == NULL) {
54 PORT_SetError (SEC_ERROR_EXTENSION_NOT_FOUND);
55 return (SECFailure);
56 }
57 if (value)
58 rv = SECITEM_CopyItem(NULL, value, &ext->value);
59 return (rv);
60 }
61
62
63 SECStatus
64 CERT_GetExtenCriticality (CERTCertExtension **extensions, int tag, PRBool *isCritical)
65 {
66 CERTCertExtension *ext;
67 SECOidData *oid;
68
69 if (!isCritical)
70 return (SECSuccess);
71
72 /* find the extension in the extensions list */
73 oid = SECOID_FindOIDByTag((SECOidTag)tag);
74 if ( !oid ) {
75 return(SECFailure);
76 }
77 ext = GetExtension (extensions, &oid->oid);
78 if (ext == NULL) {
79 PORT_SetError (SEC_ERROR_EXTENSION_NOT_FOUND);
80 return (SECFailure);
81 }
82
83 /* If the criticality is omitted, then it is false by default.
84 ex->critical.data is NULL */
85 if (ext->critical.data == NULL)
86 *isCritical = PR_FALSE;
87 else
88 *isCritical = (ext->critical.data[0] == 0xff) ? PR_TRUE : PR_FALSE;
89 return (SECSuccess);
90 }
91
92 SECStatus
93 cert_FindExtension(CERTCertExtension **extensions, int tag, SECItem *value)
94 {
95 SECOidData *oid;
96
97 oid = SECOID_FindOIDByTag((SECOidTag)tag);
98 if ( !oid ) {
99 return(SECFailure);
100 }
101
102 return(cert_FindExtensionByOID(extensions, &oid->oid, value));
103 }
104
105
106 typedef struct _extNode {
107 struct _extNode *next;
108 CERTCertExtension *ext;
109 } extNode;
110
111 typedef struct {
112 void (*setExts)(void *object, CERTCertExtension **exts);
113 void *object;
114 PLArenaPool *ownerArena;
115 PLArenaPool *arena;
116 extNode *head;
117 int count;
118 }extRec;
119
120 /*
121 * cert_StartExtensions
122 *
123 * NOTE: This interface changed significantly to remove knowledge
124 * about callers data structures (owner objects)
125 */
126 void *
127 cert_StartExtensions(void *owner, PLArenaPool *ownerArena,
128 void (*setExts)(void *object, CERTCertExtension **exts))
129 {
130 PLArenaPool *arena;
131 extRec *handle;
132
133 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
134 if ( !arena ) {
135 return(0);
136 }
137
138 handle = (extRec *)PORT_ArenaAlloc(arena, sizeof(extRec));
139 if ( !handle ) {
140 PORT_FreeArena(arena, PR_FALSE);
141 return(0);
142 }
143
144 handle->object = owner;
145 handle->ownerArena = ownerArena;
146 handle->setExts = setExts;
147
148 handle->arena = arena;
149 handle->head = 0;
150 handle->count = 0;
151
152 return(handle);
153 }
154
155 static unsigned char hextrue = 0xff;
156
157 /*
158 * Note - assumes that data pointed to by oid->data will not move
159 */
160 SECStatus
161 CERT_AddExtensionByOID (void *exthandle, SECItem *oid, SECItem *value,
162 PRBool critical, PRBool copyData)
163 {
164 CERTCertExtension *ext;
165 SECStatus rv;
166 extNode *node;
167 extRec *handle;
168
169 handle = (extRec *)exthandle;
170
171 /* allocate space for extension and list node */
172 ext = (CERTCertExtension*)PORT_ArenaZAlloc(handle->ownerArena,
173 sizeof(CERTCertExtension));
174 if ( !ext ) {
175 return(SECFailure);
176 }
177
178 node = (extNode*)PORT_ArenaAlloc(handle->arena, sizeof(extNode));
179 if ( !node ) {
180 return(SECFailure);
181 }
182
183 /* add to list */
184 node->next = handle->head;
185 handle->head = node;
186
187 /* point to ext struct */
188 node->ext = ext;
189
190 /* the object ID of the extension */
191 ext->id = *oid;
192
193 /* set critical field */
194 if ( critical ) {
195 ext->critical.data = (unsigned char*)&hextrue;
196 ext->critical.len = 1;
197 }
198
199 /* set the value */
200 if ( copyData ) {
201 rv = SECITEM_CopyItem(handle->ownerArena, &ext->value, value);
202 if ( rv ) {
203 return(SECFailure);
204 }
205 } else {
206 ext->value = *value;
207 }
208
209 handle->count++;
210
211 return(SECSuccess);
212
213 }
214
215 SECStatus
216 CERT_AddExtension(void *exthandle, int idtag, SECItem *value,
217 PRBool critical, PRBool copyData)
218 {
219 SECOidData *oid;
220
221 oid = SECOID_FindOIDByTag((SECOidTag)idtag);
222 if ( !oid ) {
223 return(SECFailure);
224 }
225
226 return(CERT_AddExtensionByOID(exthandle, &oid->oid, value, critical, copyData));
227 }
228
229 SECStatus
230 CERT_EncodeAndAddExtension(void *exthandle, int idtag, void *value,
231 PRBool critical, const SEC_ASN1Template *atemplate)
232 {
233 extRec *handle;
234 SECItem *encitem;
235
236 handle = (extRec *)exthandle;
237
238 encitem = SEC_ASN1EncodeItem(handle->ownerArena, NULL, value, atemplate);
239 if ( encitem == NULL ) {
240 return(SECFailure);
241 }
242
243 return CERT_AddExtension(exthandle, idtag, encitem, critical, PR_FALSE);
244 }
245
246 void
247 PrepareBitStringForEncoding (SECItem *bitsmap, SECItem *value)
248 {
249 unsigned char onebyte;
250 unsigned int i, len = 0;
251
252 /* to prevent warning on some platform at compile time */
253 onebyte = '\0';
254 /* Get the position of the right-most turn-on bit */
255 for (i = 0; i < (value->len ) * 8; ++i) {
256 if (i % 8 == 0)
257 onebyte = value->data[i/8];
258 if (onebyte & 0x80)
259 len = i;
260 onebyte <<= 1;
261
262 }
263 bitsmap->data = value->data;
264 /* Add one here since we work with base 1 */
265 bitsmap->len = len + 1;
266 }
267
268 SECStatus
269 CERT_EncodeAndAddBitStrExtension (void *exthandle, int idtag,
270 SECItem *value, PRBool critical)
271 {
272 SECItem bitsmap;
273
274 PrepareBitStringForEncoding (&bitsmap, value);
275 return (CERT_EncodeAndAddExtension
276 (exthandle, idtag, &bitsmap, critical,
277 SEC_ASN1_GET(SEC_BitStringTemplate)));
278 }
279
280 SECStatus
281 CERT_FinishExtensions(void *exthandle)
282 {
283 extRec *handle;
284 extNode *node;
285 CERTCertExtension **exts;
286 SECStatus rv = SECFailure;
287
288 handle = (extRec *)exthandle;
289
290 /* allocate space for extensions array */
291 exts = PORT_ArenaNewArray(handle->ownerArena, CERTCertExtension *,
292 handle->count + 1);
293 if (exts == NULL) {
294 goto loser;
295 }
296
297 /* put extensions in owner object and update its version number */
298
299 #ifdef OLD
300 switch (handle->type) {
301 case CertificateExtensions:
302 handle->owner.cert->extensions = exts;
303 DER_SetUInteger (ownerArena, &(handle->owner.cert->version),
304 SEC_CERTIFICATE_VERSION_3);
305 break;
306 case CrlExtensions:
307 handle->owner.crl->extensions = exts;
308 DER_SetUInteger (ownerArena, &(handle->owner.crl->version),
309 SEC_CRL_VERSION_2);
310 break;
311 case OCSPRequestExtensions:
312 handle->owner.request->tbsRequest->requestExtensions = exts;
313 break;
314 case OCSPSingleRequestExtensions:
315 handle->owner.singleRequest->singleRequestExtensions = exts;
316 break;
317 case OCSPResponseSingleExtensions:
318 handle->owner.singleResponse->singleExtensions = exts;
319 break;
320 }
321 #endif
322
323 handle->setExts(handle->object, exts);
324
325 /* update the version number */
326
327 /* copy each extension pointer */
328 node = handle->head;
329 while ( node ) {
330 *exts = node->ext;
331
332 node = node->next;
333 exts++;
334 }
335
336 /* terminate the array of extensions */
337 *exts = 0;
338
339 rv = SECSuccess;
340
341 loser:
342 /* free working arena */
343 PORT_FreeArena(handle->arena, PR_FALSE);
344 return rv;
345 }
346
347 SECStatus
348 CERT_MergeExtensions(void *exthandle, CERTCertExtension **extensions)
349 {
350 CERTCertExtension *ext;
351 SECStatus rv = SECSuccess;
352 SECOidTag tag;
353 extNode *node;
354 extRec *handle = exthandle;
355
356 if (!exthandle || !extensions) {
357 PORT_SetError(SEC_ERROR_INVALID_ARGS);
358 return SECFailure;
359 }
360 while ((ext = *extensions++) != NULL) {
361 tag = SECOID_FindOIDTag(&ext->id);
362 for (node=handle->head; node != NULL; node=node->next) {
363 if (tag == 0) {
364 if (SECITEM_ItemsAreEqual(&ext->id, &node->ext->id))
365 break;
366 }
367 else {
368 if (SECOID_FindOIDTag(&node->ext->id) == tag) {
369 break;
370 }
371 }
372 }
373 if (node == NULL) {
374 PRBool critical = (ext->critical.len != 0 &&
375 ext->critical.data[ext->critical.len - 1] != 0);
376 if (critical && tag == SEC_OID_UNKNOWN) {
377 PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
378 rv = SECFailure;
379 break;
380 }
381 /* add to list */
382 rv = CERT_AddExtensionByOID (exthandle, &ext->id, &ext->value,
383 critical, PR_TRUE);
384 if (rv != SECSuccess)
385 break;
386 }
387 }
388 return rv;
389 }
390
391 /*
392 * get the value of the Netscape Certificate Type Extension
393 */
394 SECStatus
395 CERT_FindBitStringExtension (CERTCertExtension **extensions, int tag,
396 SECItem *retItem)
397 {
398 SECItem wrapperItem, tmpItem = {siBuffer,0};
399 SECStatus rv;
400 PLArenaPool *arena = NULL;
401
402 wrapperItem.data = NULL;
403 tmpItem.data = NULL;
404
405 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
406
407 if ( ! arena ) {
408 return(SECFailure);
409 }
410
411 rv = cert_FindExtension(extensions, tag, &wrapperItem);
412 if ( rv != SECSuccess ) {
413 goto loser;
414 }
415
416 rv = SEC_QuickDERDecodeItem(arena, &tmpItem,
417 SEC_ASN1_GET(SEC_BitStringTemplate),
418 &wrapperItem);
419
420 if ( rv != SECSuccess ) {
421 goto loser;
422 }
423
424 retItem->data = (unsigned char *)PORT_Alloc( ( tmpItem.len + 7 ) >> 3 );
425 if ( retItem->data == NULL ) {
426 goto loser;
427 }
428
429 PORT_Memcpy(retItem->data, tmpItem.data, ( tmpItem.len + 7 ) >> 3);
430 retItem->len = tmpItem.len;
431
432 rv = SECSuccess;
433 goto done;
434
435 loser:
436 rv = SECFailure;
437
438 done:
439 if ( arena ) {
440 PORT_FreeArena(arena, PR_FALSE);
441 }
442
443 if ( wrapperItem.data ) {
444 PORT_Free(wrapperItem.data);
445 }
446
447 return(rv);
448 }
449
450 PRBool
451 cert_HasCriticalExtension (CERTCertExtension **extensions)
452 {
453 CERTCertExtension **exts;
454 CERTCertExtension *ext = NULL;
455 PRBool hasCriticalExten = PR_FALSE;
456
457 exts = extensions;
458
459 if (exts) {
460 while ( *exts ) {
461 ext = *exts;
462 /* If the criticality is omitted, it's non-critical */
463 if (ext->critical.data && ext->critical.data[0] == 0xff) {
464 hasCriticalExten = PR_TRUE;
465 break;
466 }
467 exts++;
468 }
469 }
470 return (hasCriticalExten);
471 }
472
473 PRBool
474 cert_HasUnknownCriticalExten (CERTCertExtension **extensions)
475 {
476 CERTCertExtension **exts;
477 CERTCertExtension *ext = NULL;
478 PRBool hasUnknownCriticalExten = PR_FALSE;
479
480 exts = extensions;
481
482 if (exts) {
483 while ( *exts ) {
484 ext = *exts;
485 /* If the criticality is omitted, it's non-critical.
486 If an extension is critical, make sure that we know
487 how to process the extension.
488 */
489 if (ext->critical.data && ext->critical.data[0] == 0xff) {
490 if (SECOID_KnownCertExtenOID (&ext->id) == PR_FALSE) {
491 hasUnknownCriticalExten = PR_TRUE;
492 break;
493 }
494 }
495 exts++;
496 }
497 }
498 return (hasUnknownCriticalExten);
499 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)