Coverage Report

Created: 2026-04-04 06:13

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