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
breakLines(char * string)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 *
CERT_DecodeCertificatePoliciesExtension(const SECItem * extnValue)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
CERT_DestroyCertificatePoliciesExtension(CERTCertificatePolicies * policies)202 CERT_DestroyCertificatePoliciesExtension(CERTCertificatePolicies *policies)
203 {
204     if (policies != NULL) {
205         PORT_FreeArena(policies->arena, PR_FALSE);
206     }
207     return;
208 }
209 
210 CERTCertificatePolicyMappings *
CERT_DecodePolicyMappingsExtension(SECItem * extnValue)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
CERT_DestroyPolicyMappingsExtension(CERTCertificatePolicyMappings * mappings)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
CERT_DecodePolicyConstraintsExtension(CERTCertificatePolicyConstraints * decodedValue,const SECItem * encodedValue)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
CERT_DecodeInhibitAnyExtension(CERTCertificateInhibitAny * decodedValue,SECItem * encodedValue)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 *
CERT_DecodeUserNotice(SECItem * noticeItem)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
CERT_DestroyUserNotice(CERTUserNotice * userNotice)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
CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb,void * cbarg)430 CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg)
431 {
432     policyStringCB = cb;
433     policyStringCBArg = cbarg;
434     return;
435 }
436 
437 char *
stringFromUserNotice(SECItem * noticeItem)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 *
CERT_GetCertCommentString(CERTCertificate * cert)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 *
CERT_DecodeOidSequence(const SECItem * seqItem)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
CERT_DestroyOidSequence(CERTOidSequence * oidSeq)638 CERT_DestroyOidSequence(CERTOidSequence *oidSeq)
639 {
640     if (oidSeq != NULL) {
641         PORT_FreeArena(oidSeq->arena, PR_FALSE);
642     }
643     return;
644 }
645 
646 PRBool
CERT_GovtApprovedBitSet(CERTCertificate * cert)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
CERT_EncodePolicyConstraintsExtension(PLArenaPool * arena,CERTCertificatePolicyConstraints * constr,SECItem * dest)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
CERT_EncodePolicyMappingExtension(PLArenaPool * arena,CERTCertificatePolicyMappings * mapping,SECItem * dest)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
CERT_EncodeCertPoliciesExtension(PLArenaPool * arena,CERTPolicyInfo ** info,SECItem * dest)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
CERT_EncodeUserNotice(PLArenaPool * arena,CERTUserNotice * notice,SECItem * dest)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
CERT_EncodeNoticeReference(PLArenaPool * arena,CERTNoticeReference * reference,SECItem * dest)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
CERT_EncodeInhibitAnyExtension(PLArenaPool * arena,CERTCertificateInhibitAny * certInhibitAny,SECItem * dest)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 }
807