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 * Support for various policy related extensions | |
7 */ | |
8 | |
9 #include "seccomon.h" | |
10 #include "secport.h" | |
11 #include "secder.h" | |
12 #include "cert.h" | |
13 #include "secoid.h" | |
14 #include "secasn1.h" | |
15 #include "secerr.h" | |
16 #include "nspr.h" | |
17 | |
18 SEC_ASN1_MKSUB(SEC_IntegerTemplate) | |
19 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) | |
20 | |
21 const SEC_ASN1Template CERT_DisplayTextTypeTemplate[] = { | |
22 { SEC_ASN1_CHOICE, offsetof(SECItem, type), 0, sizeof(SECItem) }, | |
23 { SEC_ASN1_IA5_STRING, 0, 0, siAsciiString }, | |
24 { SEC_ASN1_VISIBLE_STRING, 0, 0, siVisibleString }, | |
25 { SEC_ASN1_BMP_STRING, 0, 0, siBMPString }, | |
26 { SEC_ASN1_UTF8_STRING, 0, 0, siUTF8String }, | |
27 { 0 } | |
28 }; | |
29 | |
30 const SEC_ASN1Template CERT_NoticeReferenceTemplate[] = { | |
31 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNoticeReference) }, | |
32 { SEC_ASN1_INLINE, offsetof(CERTNoticeReference, organization), | |
33 CERT_DisplayTextTypeTemplate, 0 }, | |
34 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, | |
35 offsetof(CERTNoticeReference, noticeNumbers), | |
36 SEC_ASN1_SUB(SEC_IntegerTemplate) }, | |
37 { 0 } | |
38 }; | |
39 | |
40 const SEC_ASN1Template CERT_UserNoticeTemplate[] = { | |
41 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTUserNotice) }, | |
42 { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, | |
43 offsetof(CERTUserNotice, noticeReference), CERT_NoticeReferenceTemplate, | |
44 0 }, | |
45 { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, | |
46 offsetof(CERTUserNotice, displayText), CERT_DisplayTextTypeTemplate, 0 }, | |
47 { 0 } | |
48 }; | |
49 | |
50 const SEC_ASN1Template CERT_PolicyQualifierTemplate[] = { | |
51 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPolicyQualifier) }, | |
52 { SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyQualifier, qualifierID) }, | |
53 { SEC_ASN1_ANY, offsetof(CERTPolicyQualifier, qualifierValue) }, | |
54 { 0 } | |
55 }; | |
56 | |
57 const SEC_ASN1Template CERT_PolicyInfoTemplate[] = { | |
58 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPolicyInfo) }, | |
59 { SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyInfo, policyID) }, | |
60 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL, | |
61 offsetof(CERTPolicyInfo, policyQualifiers), | |
62 CERT_PolicyQualifierTemplate }, | |
63 { 0 } | |
64 }; | |
65 | |
66 const SEC_ASN1Template CERT_CertificatePoliciesTemplate[] = { | |
67 { SEC_ASN1_SEQUENCE_OF, offsetof(CERTCertificatePolicies, policyInfos), | |
68 CERT_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) } | |
69 }; | |
70 | |
71 const SEC_ASN1Template CERT_PolicyMapTemplate[] = { | |
72 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPolicyMap) }, | |
73 { SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyMap, issuerDomainPolicy) }, | |
74 { SEC_ASN1_OBJECT_ID, offsetof(CERTPolicyMap, subjectDomainPolicy) }, | |
75 { 0 } | |
76 }; | |
77 | |
78 const SEC_ASN1Template CERT_PolicyMappingsTemplate[] = { | |
79 { SEC_ASN1_SEQUENCE_OF, offsetof(CERTCertificatePolicyMappings, policyMaps), | |
80 CERT_PolicyMapTemplate, sizeof(CERTPolicyMap) } | |
81 }; | |
82 | |
83 const SEC_ASN1Template CERT_PolicyConstraintsTemplate[] = { | |
84 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCertificatePolicyConstraints) }, | |
85 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, | |
86 offsetof(CERTCertificatePolicyConstraints, explicitPolicySkipCerts), | |
87 SEC_ASN1_SUB(SEC_IntegerTemplate) }, | |
88 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, | |
89 offsetof(CERTCertificatePolicyConstraints, inhibitMappingSkipCerts), | |
90 SEC_ASN1_SUB(SEC_IntegerTemplate) }, | |
91 { 0 } | |
92 }; | |
93 | |
94 const SEC_ASN1Template CERT_InhibitAnyTemplate[] = { | |
95 { SEC_ASN1_INTEGER, | |
96 offsetof(CERTCertificateInhibitAny, inhibitAnySkipCerts), NULL, | |
97 sizeof(CERTCertificateInhibitAny) } | |
98 }; | |
99 | |
100 static void | |
101 breakLines(char *string) | |
102 { | |
103 char *tmpstr; | |
104 char *lastspace = NULL; | |
105 int curlen = 0; | |
106 int c; | |
107 | |
108 tmpstr = string; | |
109 | |
110 while ((c = *tmpstr) != '\0') { | |
111 switch (c) { | |
112 case ' ': | |
113 lastspace = tmpstr; | |
114 break; | |
115 case '\n': | |
116 lastspace = NULL; | |
117 curlen = 0; | |
118 break; | |
119 } | |
120 | |
121 if ((curlen >= 55) && (lastspace != NULL)) { | |
122 *lastspace = '\n'; | |
123 curlen = (tmpstr - lastspace); | |
124 lastspace = NULL; | |
125 } | |
126 | |
127 curlen++; | |
128 tmpstr++; | |
129 } | |
130 | |
131 return; | |
132 } | |
133 | |
134 CERTCertificatePolicies * | |
135 CERT_DecodeCertificatePoliciesExtension(const SECItem *extnValue) | |
136 { | |
137 PLArenaPool *arena = NULL; | |
138 SECStatus rv; | |
139 CERTCertificatePolicies *policies; | |
140 CERTPolicyInfo **policyInfos, *policyInfo; | |
141 CERTPolicyQualifier **policyQualifiers, *policyQualifier; | |
142 SECItem newExtnValue; | |
143 | |
144 /* make a new arena */ | |
145 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
146 | |
147 if (!arena) { | |
148 goto loser; | |
149 } | |
150 | |
151 /* allocate the certificate policies structure */ | |
152 policies = (CERTCertificatePolicies *)PORT_ArenaZAlloc( | |
153 arena, sizeof(CERTCertificatePolicies)); | |
154 | |
155 if (policies == NULL) { | |
156 goto loser; | |
157 } | |
158 | |
159 policies->arena = arena; | |
160 | |
161 /* copy the DER into the arena, since Quick DER returns data that points | |
162 into the DER input, which may get freed by the caller */ | |
163 rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue); | |
164 if (rv != SECSuccess) { | |
165 goto loser; | |
166 } | |
167 | |
168 /* decode the policy info */ | |
169 rv = SEC_QuickDERDecodeItem( | |
170 arena, policies, CERT_CertificatePoliciesTemplate, &newExtnValue); | |
171 | |
172 if (rv != SECSuccess) { | |
173 goto loser; | |
174 } | |
175 | |
176 /* initialize the oid tags */ | |
177 policyInfos = policies->policyInfos; | |
178 while (*policyInfos != NULL) { | |
179 policyInfo = *policyInfos; | |
180 policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID); | |
181 policyQualifiers = policyInfo->policyQualifiers; | |
182 while (policyQualifiers != NULL && *policyQualifiers != NULL) { | |
183 policyQualifier = *policyQualifiers; | |
184 policyQualifier->oid = | |
185 SECOID_FindOIDTag(&policyQualifier->qualifierID); | |
186 policyQualifiers++; | |
187 } | |
188 policyInfos++; | |
189 } | |
190 | |
191 return (policies); | |
192 | |
193 loser: | |
194 if (arena != NULL) { | |
195 PORT_FreeArena(arena, PR_FALSE); | |
196 } | |
197 | |
198 return (NULL); | |
199 } | |
200 | |
201 void | |
202 CERT_DestroyCertificatePoliciesExtension(CERTCertificatePolicies *policies) | |
203 { | |
204 if (policies != NULL) { | |
205 PORT_FreeArena(policies->arena, PR_FALSE); | |
206 } | |
207 return; | |
208 } | |
209 | |
210 CERTCertificatePolicyMappings * | |
211 CERT_DecodePolicyMappingsExtension(SECItem *extnValue) | |
212 { | |
213 PLArenaPool *arena = NULL; | |
214 SECStatus rv; | |
215 CERTCertificatePolicyMappings *mappings; | |
216 SECItem newExtnValue; | |
217 | |
218 /* make a new arena */ | |
219 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
220 if (!arena) { | |
221 goto loser; | |
222 } | |
223 | |
224 /* allocate the policy mappings structure */ | |
225 mappings = (CERTCertificatePolicyMappings *)PORT_ArenaZAlloc( | |
226 arena, sizeof(CERTCertificatePolicyMappings)); | |
227 if (mappings == NULL) { | |
228 goto loser; | |
229 } | |
230 mappings->arena = arena; | |
231 | |
232 /* copy the DER into the arena, since Quick DER returns data that points | |
233 into the DER input, which may get freed by the caller */ | |
234 rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue); | |
235 if (rv != SECSuccess) { | |
236 goto loser; | |
237 } | |
238 | |
239 /* decode the policy mappings */ | |
240 rv = SEC_QuickDERDecodeItem(arena, mappings, CERT_PolicyMappingsTemplate, | |
241 &newExtnValue); | |
242 if (rv != SECSuccess) { | |
243 goto loser; | |
244 } | |
245 | |
246 return (mappings); | |
247 | |
248 loser: | |
249 if (arena != NULL) { | |
250 PORT_FreeArena(arena, PR_FALSE); | |
251 } | |
252 | |
253 return (NULL); | |
254 } | |
255 | |
256 SECStatus | |
257 CERT_DestroyPolicyMappingsExtension(CERTCertificatePolicyMappings *mappings) | |
258 { | |
259 if (mappings != NULL) { | |
260 PORT_FreeArena(mappings->arena, PR_FALSE); | |
261 } | |
262 return SECSuccess; | |
263 } | |
264 | |
265 SECStatus | |
266 CERT_DecodePolicyConstraintsExtension( | |
267 CERTCertificatePolicyConstraints *decodedValue, const SECItem *encodedValue) | |
268 { | |
269 CERTCertificatePolicyConstraints decodeContext; | |
270 PLArenaPool *arena = NULL; | |
271 SECStatus rv = SECSuccess; | |
272 | |
273 /* initialize so we can tell when an optional component is omitted */ | |
274 PORT_Memset(&decodeContext, 0, sizeof(decodeContext)); | |
275 | |
276 /* make a new arena */ | |
277 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
278 if (!arena) { | |
279 return SECFailure; | |
280 } | |
281 | |
282 do { | |
283 /* decode the policy constraints */ | |
284 rv = SEC_QuickDERDecodeItem(arena, &decodeContext, | |
285 CERT_PolicyConstraintsTemplate, | |
286 encodedValue); | |
287 | |
288 if (rv != SECSuccess) { | |
289 break; | |
290 } | |
291 | |
292 if (decodeContext.explicitPolicySkipCerts.len == 0) { | |
293 *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = -1; | |
294 } else { | |
295 *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = | |
296 DER_GetInteger(&decodeContext.explicitPolicySkipCerts); | |
297 } | |
298 | |
299 if (decodeContext.inhibitMappingSkipCerts.len == 0) { | |
300 *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = -1; | |
301 } else { | |
302 *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = | |
303 DER_GetInteger(&decodeContext.inhibitMappingSkipCerts); | |
304 } | |
305 | |
306 if ((*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data == | |
307 PR_INT32_MIN) || | |
308 (*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data == | |
309 PR_INT32_MAX) || | |
310 (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data == | |
311 PR_INT32_MIN) || | |
312 (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data == | |
313 PR_INT32_MAX)) { | |
314 rv = SECFailure; | |
315 } | |
316 | |
317 } while (0); | |
318 | |
319 PORT_FreeArena(arena, PR_FALSE); | |
320 return (rv); | |
321 } | |
322 | |
323 SECStatus | |
324 CERT_DecodeInhibitAnyExtension(CERTCertificateInhibitAny *decodedValue, | |
325 SECItem *encodedValue) | |
326 { | |
327 CERTCertificateInhibitAny decodeContext; | |
328 PLArenaPool *arena = NULL; | |
329 SECStatus rv = SECSuccess; | |
330 | |
331 /* make a new arena */ | |
332 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
333 if (!arena) { | |
334 return SECFailure; | |
335 } | |
336 | |
337 do { | |
338 | |
339 /* decode the policy mappings */ | |
340 decodeContext.inhibitAnySkipCerts.type = siUnsignedInteger; | |
341 rv = SEC_QuickDERDecodeItem(arena, &decodeContext, | |
342 CERT_InhibitAnyTemplate, encodedValue); | |
343 | |
344 if (rv != SECSuccess) { | |
345 break; | |
346 } | |
347 | |
348 *(PRInt32 *)decodedValue->inhibitAnySkipCerts.data = | |
349 DER_GetInteger(&decodeContext.inhibitAnySkipCerts); | |
350 | |
351 } while (0); | |
352 | |
353 PORT_FreeArena(arena, PR_FALSE); | |
354 return (rv); | |
355 } | |
356 | |
357 CERTUserNotice * | |
358 CERT_DecodeUserNotice(SECItem *noticeItem) | |
359 { | |
360 PLArenaPool *arena = NULL; | |
361 SECStatus rv; | |
362 CERTUserNotice *userNotice; | |
363 SECItem newNoticeItem; | |
364 | |
365 /* make a new arena */ | |
366 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
367 | |
368 if (!arena) { | |
369 goto loser; | |
370 } | |
371 | |
372 /* allocate the userNotice structure */ | |
373 userNotice = | |
374 (CERTUserNotice *)PORT_ArenaZAlloc(arena, sizeof(CERTUserNotice)); | |
375 | |
376 if (userNotice == NULL) { | |
377 goto loser; | |
378 } | |
379 | |
380 userNotice->arena = arena; | |
381 | |
382 /* copy the DER into the arena, since Quick DER returns data that points | |
383 into the DER input, which may get freed by the caller */ | |
384 rv = SECITEM_CopyItem(arena, &newNoticeItem, noticeItem); | |
385 if (rv != SECSuccess) { | |
386 goto loser; | |
387 } | |
388 | |
389 /* decode the user notice */ | |
390 rv = SEC_QuickDERDecodeItem(arena, userNotice, CERT_UserNoticeTemplate, | |
391 &newNoticeItem); | |
392 | |
393 if (rv != SECSuccess) { | |
394 goto loser; | |
395 } | |
396 | |
397 if (userNotice->derNoticeReference.data != NULL) { | |
398 | |
399 rv = SEC_QuickDERDecodeItem(arena, &userNotice->noticeReference, | |
400 CERT_NoticeReferenceTemplate, | |
401 &userNotice->derNoticeReference); | |
402 if (rv == SECFailure) { | |
403 goto loser; | |
404 } | |
405 } | |
406 | |
407 return (userNotice); | |
408 | |
409 loser: | |
410 if (arena != NULL) { | |
411 PORT_FreeArena(arena, PR_FALSE); | |
412 } | |
413 | |
414 return (NULL); | |
415 } | |
416 | |
417 void | |
418 CERT_DestroyUserNotice(CERTUserNotice *userNotice) | |
419 { | |
420 if (userNotice != NULL) { | |
421 PORT_FreeArena(userNotice->arena, PR_FALSE); | |
422 } | |
423 return; | |
424 } | |
425 | |
426 static CERTPolicyStringCallback policyStringCB = NULL; | |
427 static void *policyStringCBArg = NULL; | |
428 | |
429 void | |
430 CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg) | |
431 { | |
432 policyStringCB = cb; | |
433 policyStringCBArg = cbarg; | |
434 return; | |
435 } | |
436 | |
437 char * | |
438 stringFromUserNotice(SECItem *noticeItem) | |
439 { | |
440 SECItem *org; | |
441 unsigned int len, headerlen; | |
442 char *stringbuf; | |
443 CERTUserNotice *userNotice; | |
444 char *policystr; | |
445 char *retstr = NULL; | |
446 SECItem *displayText; | |
447 SECItem **noticeNumbers; | |
448 unsigned int strnum; | |
449 | |
450 /* decode the user notice */ | |
451 userNotice = CERT_DecodeUserNotice(noticeItem); | |
452 if (userNotice == NULL) { | |
453 return (NULL); | |
454 } | |
455 | |
456 org = &userNotice->noticeReference.organization; | |
457 if ((org->len != 0) && (policyStringCB != NULL)) { | |
458 /* has a noticeReference */ | |
459 | |
460 /* extract the org string */ | |
461 len = org->len; | |
462 stringbuf = (char *)PORT_Alloc(len + 1); | |
463 if (stringbuf != NULL) { | |
464 PORT_Memcpy(stringbuf, org->data, len); | |
465 stringbuf[len] = '\0'; | |
466 | |
467 noticeNumbers = userNotice->noticeReference.noticeNumbers; | |
468 while (*noticeNumbers != NULL) { | |
469 /* XXX - only one byte integers right now*/ | |
470 strnum = (*noticeNumbers)->data[0]; | |
471 policystr = | |
472 (*policyStringCB)(stringbuf, strnum, policyStringCBArg); | |
473 if (policystr != NULL) { | |
474 if (retstr != NULL) { | |
475 retstr = PR_sprintf_append(retstr, "\n%s", policystr); | |
476 } else { | |
477 retstr = PR_sprintf_append(retstr, "%s", policystr); | |
478 } | |
479 | |
480 PORT_Free(policystr); | |
481 } | |
482 | |
483 noticeNumbers++; | |
484 } | |
485 | |
486 PORT_Free(stringbuf); | |
487 } | |
488 } | |
489 | |
490 if (retstr == NULL) { | |
491 if (userNotice->displayText.len != 0) { | |
492 displayText = &userNotice->displayText; | |
493 | |
494 if (displayText->len > 2) { | |
495 if (displayText->data[0] == SEC_ASN1_VISIBLE_STRING) { | |
496 headerlen = 2; | |
497 if (displayText->data[1] & 0x80) { | |
498 /* multibyte length */ | |
499 headerlen += (displayText->data[1] & 0x7f); | |
500 } | |
501 | |
502 len = displayText->len - headerlen; | |
503 retstr = (char *)PORT_Alloc(len + 1); | |
504 if (retstr != NULL) { | |
505 PORT_Memcpy(retstr, &displayText->data[headerlen], len); | |
506 retstr[len] = '\0'; | |
507 } | |
508 } | |
509 } | |
510 } | |
511 } | |
512 | |
513 CERT_DestroyUserNotice(userNotice); | |
514 | |
515 return (retstr); | |
516 } | |
517 | |
518 char * | |
519 CERT_GetCertCommentString(CERTCertificate *cert) | |
520 { | |
521 char *retstring = NULL; | |
522 SECStatus rv; | |
523 SECItem policyItem; | |
524 CERTCertificatePolicies *policies = NULL; | |
525 CERTPolicyInfo **policyInfos; | |
526 CERTPolicyQualifier **policyQualifiers, *qualifier; | |
527 | |
528 policyItem.data = NULL; | |
529 | |
530 rv = CERT_FindCertExtension(cert, SEC_OID_X509_CERTIFICATE_POLICIES, | |
531 &policyItem); | |
532 if (rv != SECSuccess) { | |
533 goto nopolicy; | |
534 } | |
535 | |
536 policies = CERT_DecodeCertificatePoliciesExtension(&policyItem); | |
537 if (policies == NULL) { | |
538 goto nopolicy; | |
539 } | |
540 | |
541 policyInfos = policies->policyInfos; | |
542 /* search through policyInfos looking for the verisign policy */ | |
543 while (*policyInfos != NULL) { | |
544 if ((*policyInfos)->oid == SEC_OID_VERISIGN_USER_NOTICES) { | |
545 policyQualifiers = (*policyInfos)->policyQualifiers; | |
546 /* search through the policy qualifiers looking for user notice */ | |
547 while (policyQualifiers != NULL && *policyQualifiers != NULL) { | |
548 qualifier = *policyQualifiers; | |
549 if (qualifier->oid == SEC_OID_PKIX_USER_NOTICE_QUALIFIER) { | |
550 retstring = | |
551 stringFromUserNotice(&qualifier->qualifierValue); | |
552 break; | |
553 } | |
554 | |
555 policyQualifiers++; | |
556 } | |
557 break; | |
558 } | |
559 policyInfos++; | |
560 } | |
561 | |
562 nopolicy: | |
563 if (policyItem.data != NULL) { | |
564 PORT_Free(policyItem.data); | |
565 } | |
566 | |
567 if (policies != NULL) { | |
568 CERT_DestroyCertificatePoliciesExtension(policies); | |
569 } | |
570 | |
571 if (retstring == NULL) { | |
572 retstring = | |
573 CERT_FindNSStringExtension(cert, SEC_OID_NS_CERT_EXT_COMMENT); | |
574 } | |
575 | |
576 if (retstring != NULL) { | |
577 breakLines(retstring); | |
578 } | |
579 | |
580 return (retstring); | |
581 } | |
582 | |
583 const SEC_ASN1Template CERT_OidSeqTemplate[] = { | |
584 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, offsetof(CERTOidSequence, oids), | |
585 SEC_ASN1_SUB(SEC_ObjectIDTemplate) } | |
586 }; | |
587 | |
588 CERTOidSequence * | |
589 CERT_DecodeOidSequence(const SECItem *seqItem) | |
590 { | |
591 PLArenaPool *arena = NULL; | |
592 SECStatus rv; | |
593 CERTOidSequence *oidSeq; | |
594 SECItem newSeqItem; | |
595 | |
596 /* make a new arena */ | |
597 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
598 | |
599 if (!arena) { | |
600 goto loser; | |
601 } | |
602 | |
603 /* allocate the userNotice structure */ | |
604 oidSeq = | |
605 (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence)); | |
606 | |
607 if (oidSeq == NULL) { | |
608 goto loser; | |
609 } | |
610 | |
611 oidSeq->arena = arena; | |
612 | |
613 /* copy the DER into the arena, since Quick DER returns data that points | |
614 into the DER input, which may get freed by the caller */ | |
615 rv = SECITEM_CopyItem(arena, &newSeqItem, seqItem); | |
616 if (rv != SECSuccess) { | |
617 goto loser; | |
618 } | |
619 | |
620 /* decode the user notice */ | |
621 rv = | |
622 SEC_QuickDERDecodeItem(arena, oidSeq, CERT_OidSeqTemplate, &newSeqItem); | |
623 | |
624 if (rv != SECSuccess) { | |
625 goto loser; | |
626 } | |
627 | |
628 return (oidSeq); | |
629 | |
630 loser: | |
631 if (arena) { | |
632 PORT_FreeArena(arena, PR_FALSE); | |
633 } | |
634 return (NULL); | |
635 } | |
636 | |
637 void | |
638 CERT_DestroyOidSequence(CERTOidSequence *oidSeq) | |
639 { | |
640 if (oidSeq != NULL) { | |
641 PORT_FreeArena(oidSeq->arena, PR_FALSE); | |
642 } | |
643 return; | |
644 } | |
645 | |
646 PRBool | |
647 CERT_GovtApprovedBitSet(CERTCertificate *cert) | |
648 { | |
649 SECStatus rv; | |
650 SECItem extItem; | |
651 CERTOidSequence *oidSeq = NULL; | |
652 PRBool ret; | |
653 SECItem **oids; | |
654 SECItem *oid; | |
655 SECOidTag oidTag; | |
656 | |
657 extItem.data = NULL; | |
658 rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem); | |
659 if (rv != SECSuccess) { | |
660 goto loser; | |
661 } | |
662 | |
663 oidSeq = CERT_DecodeOidSequence(&extItem); | |
664 if (oidSeq == NULL) { | |
665 goto loser; | |
666 } | |
667 | |
668 oids = oidSeq->oids; | |
669 while (oids != NULL && *oids != NULL) { | |
670 oid = *oids; | |
671 | |
672 oidTag = SECOID_FindOIDTag(oid); | |
673 | |
674 if (oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) { | |
675 goto success; | |
676 } | |
677 | |
678 oids++; | |
679 } | |
680 | |
681 loser: | |
682 ret = PR_FALSE; | |
683 goto done; | |
684 success: | |
685 ret = PR_TRUE; | |
686 done: | |
687 if (oidSeq != NULL) { | |
688 CERT_DestroyOidSequence(oidSeq); | |
689 } | |
690 if (extItem.data != NULL) { | |
691 PORT_Free(extItem.data); | |
692 } | |
693 return (ret); | |
694 } | |
695 | |
696 SECStatus | |
697 CERT_EncodePolicyConstraintsExtension(PLArenaPool *arena, | |
698 CERTCertificatePolicyConstraints *constr, | |
699 SECItem *dest) | |
700 { | |
701 SECStatus rv = SECSuccess; | |
702 | |
703 PORT_Assert(constr != NULL && dest != NULL); | |
704 if (constr == NULL || dest == NULL) { | |
705 return SECFailure; | |
706 } | |
707 | |
708 if (SEC_ASN1EncodeItem(arena, dest, constr, | |
709 CERT_PolicyConstraintsTemplate) == NULL) { | |
710 rv = SECFailure; | |
711 } | |
712 return (rv); | |
713 } | |
714 | |
715 SECStatus | |
716 CERT_EncodePolicyMappingExtension(PLArenaPool *arena, | |
717 CERTCertificatePolicyMappings *mapping, | |
718 SECItem *dest) | |
719 { | |
720 SECStatus rv = SECSuccess; | |
721 | |
722 PORT_Assert(mapping != NULL && dest != NULL); | |
723 if (mapping == NULL || dest == NULL) { | |
724 return SECFailure; | |
725 } | |
726 | |
727 if (SEC_ASN1EncodeItem(arena, dest, mapping, CERT_PolicyMappingsTemplate) == | |
728 NULL) { | |
729 rv = SECFailure; | |
730 } | |
731 return (rv); | |
732 } | |
733 | |
734 SECStatus | |
735 CERT_EncodeCertPoliciesExtension(PLArenaPool *arena, CERTPolicyInfo **info, | |
736 SECItem *dest) | |
737 { | |
738 SECStatus rv = SECSuccess; | |
739 | |
740 PORT_Assert(info != NULL && dest != NULL); | |
741 if (info == NULL || dest == NULL) { | |
742 return SECFailure; | |
743 } | |
744 | |
745 if (SEC_ASN1EncodeItem(arena, dest, info, | |
746 CERT_CertificatePoliciesTemplate) == NULL) { | |
747 rv = SECFailure; | |
748 } | |
749 return (rv); | |
750 } | |
751 | |
752 SECStatus | |
753 CERT_EncodeUserNotice(PLArenaPool *arena, CERTUserNotice *notice, SECItem *dest) | |
754 { | |
755 SECStatus rv = SECSuccess; | |
756 | |
757 PORT_Assert(notice != NULL && dest != NULL); | |
758 if (notice == NULL || dest == NULL) { | |
759 return SECFailure; | |
760 } | |
761 | |
762 if (SEC_ASN1EncodeItem(arena, dest, notice, CERT_UserNoticeTemplate) == | |
763 NULL) { | |
764 rv = SECFailure; | |
765 } | |
766 | |
767 return (rv); | |
768 } | |
769 | |
770 SECStatus | |
771 CERT_EncodeNoticeReference(PLArenaPool *arena, CERTNoticeReference *reference, | |
772 SECItem *dest) | |
773 { | |
774 SECStatus rv = SECSuccess; | |
775 | |
776 PORT_Assert(reference != NULL && dest != NULL); | |
777 if (reference == NULL || dest == NULL) { | |
778 return SECFailure; | |
779 } | |
780 | |
781 if (SEC_ASN1EncodeItem(arena, dest, reference, | |
782 CERT_NoticeReferenceTemplate) == NULL) { | |
783 rv = SECFailure; | |
784 } | |
785 | |
786 return (rv); | |
787 } | |
788 | |
789 SECStatus | |
790 CERT_EncodeInhibitAnyExtension(PLArenaPool *arena, | |
791 CERTCertificateInhibitAny *certInhibitAny, | |
792 SECItem *dest) | |
793 { | |
794 SECStatus rv = SECSuccess; | |
795 | |
796 PORT_Assert(certInhibitAny != NULL && dest != NULL); | |
797 if (certInhibitAny == NULL || dest == NULL) { | |
798 return SECFailure; | |
799 } | |
800 | |
801 if (SEC_ASN1EncodeItem(arena, dest, certInhibitAny, | |
802 CERT_InhibitAnyTemplate) == NULL) { | |
803 rv = SECFailure; | |
804 } | |
805 return (rv); | |
806 } | |
OLD | NEW |