Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/nss/lib/certdb/polcyxtn.c
Line
Count
Source (jump to first uncovered line)
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
            *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data =
296
0
                DER_GetInteger(&decodeContext.explicitPolicySkipCerts);
297
0
        }
298
299
0
        if (decodeContext.inhibitMappingSkipCerts.len == 0) {
300
0
            *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = -1;
301
0
        } else {
302
0
            *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data =
303
0
                DER_GetInteger(&decodeContext.inhibitMappingSkipCerts);
304
0
        }
305
306
0
        if ((*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data ==
307
0
             PR_INT32_MIN) ||
308
0
            (*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data ==
309
0
             PR_INT32_MAX) ||
310
0
            (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data ==
311
0
             PR_INT32_MIN) ||
312
0
            (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data ==
313
0
             PR_INT32_MAX)) {
314
0
            rv = SECFailure;
315
0
        }
316
317
0
    } while (0);
318
319
0
    PORT_FreeArena(arena, PR_FALSE);
320
0
    return (rv);
321
0
}
322
323
SECStatus
324
CERT_DecodeInhibitAnyExtension(CERTCertificateInhibitAny *decodedValue,
325
                               SECItem *encodedValue)
326
0
{
327
0
    CERTCertificateInhibitAny decodeContext;
328
0
    PLArenaPool *arena = NULL;
329
0
    SECStatus rv = SECSuccess;
330
331
    /* make a new arena */
332
0
    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
333
0
    if (!arena) {
334
0
        return SECFailure;
335
0
    }
336
337
0
    do {
338
339
        /* decode the policy mappings */
340
0
        decodeContext.inhibitAnySkipCerts.type = siUnsignedInteger;
341
0
        rv = SEC_QuickDERDecodeItem(arena, &decodeContext,
342
0
                                    CERT_InhibitAnyTemplate, encodedValue);
343
344
0
        if (rv != SECSuccess) {
345
0
            break;
346
0
        }
347
348
0
        *(PRInt32 *)decodedValue->inhibitAnySkipCerts.data =
349
0
            DER_GetInteger(&decodeContext.inhibitAnySkipCerts);
350
351
0
    } while (0);
352
353
0
    PORT_FreeArena(arena, PR_FALSE);
354
0
    return (rv);
355
0
}
356
357
CERTUserNotice *
358
CERT_DecodeUserNotice(SECItem *noticeItem)
359
0
{
360
0
    PLArenaPool *arena = NULL;
361
0
    SECStatus rv;
362
0
    CERTUserNotice *userNotice;
363
0
    SECItem newNoticeItem;
364
365
    /* make a new arena */
366
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
367
368
0
    if (!arena) {
369
0
        goto loser;
370
0
    }
371
372
    /* allocate the userNotice structure */
373
0
    userNotice =
374
0
        (CERTUserNotice *)PORT_ArenaZAlloc(arena, sizeof(CERTUserNotice));
375
376
0
    if (userNotice == NULL) {
377
0
        goto loser;
378
0
    }
379
380
0
    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
0
    rv = SECITEM_CopyItem(arena, &newNoticeItem, noticeItem);
385
0
    if (rv != SECSuccess) {
386
0
        goto loser;
387
0
    }
388
389
    /* decode the user notice */
390
0
    rv = SEC_QuickDERDecodeItem(arena, userNotice, CERT_UserNoticeTemplate,
391
0
                                &newNoticeItem);
392
393
0
    if (rv != SECSuccess) {
394
0
        goto loser;
395
0
    }
396
397
0
    if (userNotice->derNoticeReference.data != NULL) {
398
399
0
        rv = SEC_QuickDERDecodeItem(arena, &userNotice->noticeReference,
400
0
                                    CERT_NoticeReferenceTemplate,
401
0
                                    &userNotice->derNoticeReference);
402
0
        if (rv == SECFailure) {
403
0
            goto loser;
404
0
        }
405
0
    }
406
407
0
    return (userNotice);
408
409
0
loser:
410
0
    if (arena != NULL) {
411
0
        PORT_FreeArena(arena, PR_FALSE);
412
0
    }
413
414
0
    return (NULL);
415
0
}
416
417
void
418
CERT_DestroyUserNotice(CERTUserNotice *userNotice)
419
0
{
420
0
    if (userNotice != NULL) {
421
0
        PORT_FreeArena(userNotice->arena, PR_FALSE);
422
0
    }
423
0
    return;
424
0
}
425
426
static CERTPolicyStringCallback policyStringCB = NULL;
427
static void *policyStringCBArg = NULL;
428
429
void
430
CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg)
431
0
{
432
0
    policyStringCB = cb;
433
0
    policyStringCBArg = cbarg;
434
0
    return;
435
0
}
436
437
char *
438
stringFromUserNotice(SECItem *noticeItem)
439
0
{
440
0
    SECItem *org;
441
0
    unsigned int len, headerlen;
442
0
    char *stringbuf;
443
0
    CERTUserNotice *userNotice;
444
0
    char *policystr;
445
0
    char *retstr = NULL;
446
0
    SECItem *displayText;
447
0
    SECItem **noticeNumbers;
448
0
    unsigned int strnum;
449
450
    /* decode the user notice */
451
0
    userNotice = CERT_DecodeUserNotice(noticeItem);
452
0
    if (userNotice == NULL) {
453
0
        return (NULL);
454
0
    }
455
456
0
    org = &userNotice->noticeReference.organization;
457
0
    if ((org->len != 0) && (policyStringCB != NULL)) {
458
        /* has a noticeReference */
459
460
        /* extract the org string */
461
0
        len = org->len;
462
0
        stringbuf = (char *)PORT_Alloc(len + 1);
463
0
        if (stringbuf != NULL) {
464
0
            PORT_Memcpy(stringbuf, org->data, len);
465
0
            stringbuf[len] = '\0';
466
467
0
            noticeNumbers = userNotice->noticeReference.noticeNumbers;
468
0
            while (*noticeNumbers != NULL) {
469
                /* XXX - only one byte integers right now*/
470
0
                strnum = (*noticeNumbers)->data[0];
471
0
                policystr =
472
0
                    (*policyStringCB)(stringbuf, strnum, policyStringCBArg);
473
0
                if (policystr != NULL) {
474
0
                    if (retstr != NULL) {
475
0
                        retstr = PR_sprintf_append(retstr, "\n%s", policystr);
476
0
                    } else {
477
0
                        retstr = PR_sprintf_append(retstr, "%s", policystr);
478
0
                    }
479
480
0
                    PORT_Free(policystr);
481
0
                }
482
483
0
                noticeNumbers++;
484
0
            }
485
486
0
            PORT_Free(stringbuf);
487
0
        }
488
0
    }
489
490
0
    if (retstr == NULL) {
491
0
        if (userNotice->displayText.len != 0) {
492
0
            displayText = &userNotice->displayText;
493
494
0
            if (displayText->len > 2) {
495
0
                if (displayText->data[0] == SEC_ASN1_VISIBLE_STRING) {
496
0
                    headerlen = 2;
497
0
                    if (displayText->data[1] & 0x80) {
498
                        /* multibyte length */
499
0
                        headerlen += (displayText->data[1] & 0x7f);
500
0
                    }
501
502
0
                    len = displayText->len - headerlen;
503
0
                    retstr = (char *)PORT_Alloc(len + 1);
504
0
                    if (retstr != NULL) {
505
0
                        PORT_Memcpy(retstr, &displayText->data[headerlen], len);
506
0
                        retstr[len] = '\0';
507
0
                    }
508
0
                }
509
0
            }
510
0
        }
511
0
    }
512
513
0
    CERT_DestroyUserNotice(userNotice);
514
515
0
    return (retstr);
516
0
}
517
518
char *
519
CERT_GetCertCommentString(CERTCertificate *cert)
520
0
{
521
0
    char *retstring = NULL;
522
0
    SECStatus rv;
523
0
    SECItem policyItem;
524
0
    CERTCertificatePolicies *policies = NULL;
525
0
    CERTPolicyInfo **policyInfos;
526
0
    CERTPolicyQualifier **policyQualifiers, *qualifier;
527
528
0
    policyItem.data = NULL;
529
530
0
    rv = CERT_FindCertExtension(cert, SEC_OID_X509_CERTIFICATE_POLICIES,
531
0
                                &policyItem);
532
0
    if (rv != SECSuccess) {
533
0
        goto nopolicy;
534
0
    }
535
536
0
    policies = CERT_DecodeCertificatePoliciesExtension(&policyItem);
537
0
    if (policies == NULL) {
538
0
        goto nopolicy;
539
0
    }
540
541
0
    policyInfos = policies->policyInfos;
542
    /* search through policyInfos looking for the verisign policy */
543
0
    while (*policyInfos != NULL) {
544
0
        if ((*policyInfos)->oid == SEC_OID_VERISIGN_USER_NOTICES) {
545
0
            policyQualifiers = (*policyInfos)->policyQualifiers;
546
            /* search through the policy qualifiers looking for user notice */
547
0
            while (policyQualifiers != NULL && *policyQualifiers != NULL) {
548
0
                qualifier = *policyQualifiers;
549
0
                if (qualifier->oid == SEC_OID_PKIX_USER_NOTICE_QUALIFIER) {
550
0
                    retstring =
551
0
                        stringFromUserNotice(&qualifier->qualifierValue);
552
0
                    break;
553
0
                }
554
555
0
                policyQualifiers++;
556
0
            }
557
0
            break;
558
0
        }
559
0
        policyInfos++;
560
0
    }
561
562
0
nopolicy:
563
0
    if (policyItem.data != NULL) {
564
0
        PORT_Free(policyItem.data);
565
0
    }
566
567
0
    if (policies != NULL) {
568
0
        CERT_DestroyCertificatePoliciesExtension(policies);
569
0
    }
570
571
0
    if (retstring == NULL) {
572
0
        retstring =
573
0
            CERT_FindNSStringExtension(cert, SEC_OID_NS_CERT_EXT_COMMENT);
574
0
    }
575
576
0
    if (retstring != NULL) {
577
0
        breakLines(retstring);
578
0
    }
579
580
0
    return (retstring);
581
0
}
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
0
{
591
0
    PLArenaPool *arena = NULL;
592
0
    SECStatus rv;
593
0
    CERTOidSequence *oidSeq;
594
0
    SECItem newSeqItem;
595
596
    /* make a new arena */
597
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
598
599
0
    if (!arena) {
600
0
        goto loser;
601
0
    }
602
603
    /* allocate the userNotice structure */
604
0
    oidSeq =
605
0
        (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence));
606
607
0
    if (oidSeq == NULL) {
608
0
        goto loser;
609
0
    }
610
611
0
    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
0
    rv = SECITEM_CopyItem(arena, &newSeqItem, seqItem);
616
0
    if (rv != SECSuccess) {
617
0
        goto loser;
618
0
    }
619
620
    /* decode the user notice */
621
0
    rv =
622
0
        SEC_QuickDERDecodeItem(arena, oidSeq, CERT_OidSeqTemplate, &newSeqItem);
623
624
0
    if (rv != SECSuccess) {
625
0
        goto loser;
626
0
    }
627
628
0
    return (oidSeq);
629
630
0
loser:
631
0
    if (arena) {
632
0
        PORT_FreeArena(arena, PR_FALSE);
633
0
    }
634
0
    return (NULL);
635
0
}
636
637
void
638
CERT_DestroyOidSequence(CERTOidSequence *oidSeq)
639
0
{
640
0
    if (oidSeq != NULL) {
641
0
        PORT_FreeArena(oidSeq->arena, PR_FALSE);
642
0
    }
643
0
    return;
644
0
}
645
646
PRBool
647
CERT_GovtApprovedBitSet(CERTCertificate *cert)
648
0
{
649
0
    SECStatus rv;
650
0
    SECItem extItem;
651
0
    CERTOidSequence *oidSeq = NULL;
652
0
    PRBool ret;
653
0
    SECItem **oids;
654
0
    SECItem *oid;
655
0
    SECOidTag oidTag;
656
657
0
    extItem.data = NULL;
658
0
    rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem);
659
0
    if (rv != SECSuccess) {
660
0
        goto loser;
661
0
    }
662
663
0
    oidSeq = CERT_DecodeOidSequence(&extItem);
664
0
    if (oidSeq == NULL) {
665
0
        goto loser;
666
0
    }
667
668
0
    oids = oidSeq->oids;
669
0
    while (oids != NULL && *oids != NULL) {
670
0
        oid = *oids;
671
672
0
        oidTag = SECOID_FindOIDTag(oid);
673
674
0
        if (oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) {
675
0
            goto success;
676
0
        }
677
678
0
        oids++;
679
0
    }
680
681
0
loser:
682
0
    ret = PR_FALSE;
683
0
    goto done;
684
0
success:
685
0
    ret = PR_TRUE;
686
0
done:
687
0
    if (oidSeq != NULL) {
688
0
        CERT_DestroyOidSequence(oidSeq);
689
0
    }
690
0
    if (extItem.data != NULL) {
691
0
        PORT_Free(extItem.data);
692
0
    }
693
0
    return (ret);
694
0
}
695
696
SECStatus
697
CERT_EncodePolicyConstraintsExtension(PLArenaPool *arena,
698
                                      CERTCertificatePolicyConstraints *constr,
699
                                      SECItem *dest)
700
0
{
701
0
    SECStatus rv = SECSuccess;
702
703
0
    PORT_Assert(constr != NULL && dest != NULL);
704
0
    if (constr == NULL || dest == NULL) {
705
0
        return SECFailure;
706
0
    }
707
708
0
    if (SEC_ASN1EncodeItem(arena, dest, constr,
709
0
                           CERT_PolicyConstraintsTemplate) == NULL) {
710
0
        rv = SECFailure;
711
0
    }
712
0
    return (rv);
713
0
}
714
715
SECStatus
716
CERT_EncodePolicyMappingExtension(PLArenaPool *arena,
717
                                  CERTCertificatePolicyMappings *mapping,
718
                                  SECItem *dest)
719
0
{
720
0
    SECStatus rv = SECSuccess;
721
722
0
    PORT_Assert(mapping != NULL && dest != NULL);
723
0
    if (mapping == NULL || dest == NULL) {
724
0
        return SECFailure;
725
0
    }
726
727
0
    if (SEC_ASN1EncodeItem(arena, dest, mapping, CERT_PolicyMappingsTemplate) ==
728
0
        NULL) {
729
0
        rv = SECFailure;
730
0
    }
731
0
    return (rv);
732
0
}
733
734
SECStatus
735
CERT_EncodeCertPoliciesExtension(PLArenaPool *arena, CERTPolicyInfo **info,
736
                                 SECItem *dest)
737
0
{
738
0
    SECStatus rv = SECSuccess;
739
740
0
    PORT_Assert(info != NULL && dest != NULL);
741
0
    if (info == NULL || dest == NULL) {
742
0
        return SECFailure;
743
0
    }
744
745
0
    if (SEC_ASN1EncodeItem(arena, dest, info,
746
0
                           CERT_CertificatePoliciesTemplate) == NULL) {
747
0
        rv = SECFailure;
748
0
    }
749
0
    return (rv);
750
0
}
751
752
SECStatus
753
CERT_EncodeUserNotice(PLArenaPool *arena, CERTUserNotice *notice, SECItem *dest)
754
0
{
755
0
    SECStatus rv = SECSuccess;
756
757
0
    PORT_Assert(notice != NULL && dest != NULL);
758
0
    if (notice == NULL || dest == NULL) {
759
0
        return SECFailure;
760
0
    }
761
762
0
    if (SEC_ASN1EncodeItem(arena, dest, notice, CERT_UserNoticeTemplate) ==
763
0
        NULL) {
764
0
        rv = SECFailure;
765
0
    }
766
767
0
    return (rv);
768
0
}
769
770
SECStatus
771
CERT_EncodeNoticeReference(PLArenaPool *arena, CERTNoticeReference *reference,
772
                           SECItem *dest)
773
0
{
774
0
    SECStatus rv = SECSuccess;
775
776
0
    PORT_Assert(reference != NULL && dest != NULL);
777
0
    if (reference == NULL || dest == NULL) {
778
0
        return SECFailure;
779
0
    }
780
781
0
    if (SEC_ASN1EncodeItem(arena, dest, reference,
782
0
                           CERT_NoticeReferenceTemplate) == NULL) {
783
0
        rv = SECFailure;
784
0
    }
785
786
0
    return (rv);
787
0
}
788
789
SECStatus
790
CERT_EncodeInhibitAnyExtension(PLArenaPool *arena,
791
                               CERTCertificateInhibitAny *certInhibitAny,
792
                               SECItem *dest)
793
0
{
794
0
    SECStatus rv = SECSuccess;
795
796
0
    PORT_Assert(certInhibitAny != NULL && dest != NULL);
797
0
    if (certInhibitAny == NULL || dest == NULL) {
798
0
        return SECFailure;
799
0
    }
800
801
0
    if (SEC_ASN1EncodeItem(arena, dest, certInhibitAny,
802
0
                           CERT_InhibitAnyTemplate) == NULL) {
803
0
        rv = SECFailure;
804
0
    }
805
0
    return (rv);
806
0
}