Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/certhigh/ocspsig.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
#include "plarena.h"
6
7
#include "seccomon.h"
8
#include "secitem.h"
9
#include "secasn1.h"
10
#include "secder.h"
11
#include "cert.h"
12
#include "secerr.h"
13
#include "secoid.h"
14
#include "sechash.h"
15
#include "keyhi.h"
16
#include "cryptohi.h"
17
#include "ocsp.h"
18
#include "ocspti.h"
19
#include "ocspi.h"
20
#include "pk11pub.h"
21
22
extern const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[];
23
extern const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[];
24
extern const SEC_ASN1Template ocsp_OCSPResponseTemplate[];
25
26
ocspCertStatus *
27
ocsp_CreateCertStatus(PLArenaPool *arena,
28
                      ocspCertStatusType status,
29
                      PRTime revocationTime)
30
0
{
31
0
    ocspCertStatus *cs;
32
0
33
0
    if (!arena) {
34
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
35
0
        return NULL;
36
0
    }
37
0
38
0
    switch (status) {
39
0
        case ocspCertStatus_good:
40
0
        case ocspCertStatus_unknown:
41
0
        case ocspCertStatus_revoked:
42
0
            break;
43
0
        default:
44
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
45
0
            return NULL;
46
0
    }
47
0
48
0
    cs = PORT_ArenaZNew(arena, ocspCertStatus);
49
0
    if (!cs)
50
0
        return NULL;
51
0
    cs->certStatusType = status;
52
0
    switch (status) {
53
0
        case ocspCertStatus_good:
54
0
            cs->certStatusInfo.goodInfo = SECITEM_AllocItem(arena, NULL, 0);
55
0
            if (!cs->certStatusInfo.goodInfo)
56
0
                return NULL;
57
0
            break;
58
0
        case ocspCertStatus_unknown:
59
0
            cs->certStatusInfo.unknownInfo = SECITEM_AllocItem(arena, NULL, 0);
60
0
            if (!cs->certStatusInfo.unknownInfo)
61
0
                return NULL;
62
0
            break;
63
0
        case ocspCertStatus_revoked:
64
0
            cs->certStatusInfo.revokedInfo =
65
0
                PORT_ArenaZNew(arena, ocspRevokedInfo);
66
0
            if (!cs->certStatusInfo.revokedInfo)
67
0
                return NULL;
68
0
            cs->certStatusInfo.revokedInfo->revocationReason =
69
0
                SECITEM_AllocItem(arena, NULL, 0);
70
0
            if (!cs->certStatusInfo.revokedInfo->revocationReason)
71
0
                return NULL;
72
0
            if (DER_TimeToGeneralizedTimeArena(arena,
73
0
                                               &cs->certStatusInfo.revokedInfo->revocationTime,
74
0
                                               revocationTime) !=
75
0
                SECSuccess)
76
0
                return NULL;
77
0
            break;
78
0
        default:
79
0
            PORT_Assert(PR_FALSE);
80
0
    }
81
0
    return cs;
82
0
}
83
84
static const SEC_ASN1Template mySEC_EnumeratedTemplate[] = {
85
    { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) }
86
};
87
88
static const SEC_ASN1Template mySEC_PointerToEnumeratedTemplate[] = {
89
    { SEC_ASN1_POINTER, 0, mySEC_EnumeratedTemplate }
90
};
91
92
static const SEC_ASN1Template ocsp_EncodeRevokedInfoTemplate[] = {
93
    { SEC_ASN1_GENERALIZED_TIME,
94
      offsetof(ocspRevokedInfo, revocationTime) },
95
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
96
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
97
      offsetof(ocspRevokedInfo, revocationReason),
98
      mySEC_PointerToEnumeratedTemplate },
99
    { 0 }
100
};
101
102
static const SEC_ASN1Template ocsp_PointerToEncodeRevokedInfoTemplate[] = {
103
    { SEC_ASN1_POINTER, 0,
104
      ocsp_EncodeRevokedInfoTemplate }
105
};
106
107
static const SEC_ASN1Template mySEC_NullTemplate[] = {
108
    { SEC_ASN1_NULL, 0, NULL, sizeof(SECItem) }
109
};
110
111
static const SEC_ASN1Template ocsp_CertStatusTemplate[] = {
112
    { SEC_ASN1_CHOICE, offsetof(ocspCertStatus, certStatusType),
113
      0, sizeof(ocspCertStatus) },
114
    { SEC_ASN1_CONTEXT_SPECIFIC | 0,
115
      0, mySEC_NullTemplate, ocspCertStatus_good },
116
    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
117
          SEC_ASN1_CONTEXT_SPECIFIC | 1,
118
      offsetof(ocspCertStatus, certStatusInfo.revokedInfo),
119
      ocsp_PointerToEncodeRevokedInfoTemplate, ocspCertStatus_revoked },
120
    { SEC_ASN1_CONTEXT_SPECIFIC | 2,
121
      0, mySEC_NullTemplate, ocspCertStatus_unknown },
122
    { 0 }
123
};
124
125
static const SEC_ASN1Template mySECOID_AlgorithmIDTemplate[] = {
126
    { SEC_ASN1_SEQUENCE,
127
      0, NULL, sizeof(SECAlgorithmID) },
128
    { SEC_ASN1_OBJECT_ID,
129
      offsetof(SECAlgorithmID, algorithm) },
130
    { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
131
      offsetof(SECAlgorithmID, parameters) },
132
    { 0 }
133
};
134
135
static const SEC_ASN1Template mySEC_AnyTemplate[] = {
136
    { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
137
};
138
139
static const SEC_ASN1Template mySEC_SequenceOfAnyTemplate[] = {
140
    { SEC_ASN1_SEQUENCE_OF, 0, mySEC_AnyTemplate }
141
};
142
143
static const SEC_ASN1Template mySEC_PointerToSequenceOfAnyTemplate[] = {
144
    { SEC_ASN1_POINTER, 0, mySEC_SequenceOfAnyTemplate }
145
};
146
147
static const SEC_ASN1Template mySEC_IntegerTemplate[] = {
148
    { SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) }
149
};
150
151
static const SEC_ASN1Template mySEC_PointerToIntegerTemplate[] = {
152
    { SEC_ASN1_POINTER, 0, mySEC_IntegerTemplate }
153
};
154
155
static const SEC_ASN1Template mySEC_GeneralizedTimeTemplate[] = {
156
    { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
157
};
158
159
static const SEC_ASN1Template mySEC_PointerToGeneralizedTimeTemplate[] = {
160
    { SEC_ASN1_POINTER, 0, mySEC_GeneralizedTimeTemplate }
161
};
162
163
static const SEC_ASN1Template ocsp_myCertIDTemplate[] = {
164
    { SEC_ASN1_SEQUENCE,
165
      0, NULL, sizeof(CERTOCSPCertID) },
166
    { SEC_ASN1_INLINE,
167
      offsetof(CERTOCSPCertID, hashAlgorithm),
168
      mySECOID_AlgorithmIDTemplate },
169
    { SEC_ASN1_OCTET_STRING,
170
      offsetof(CERTOCSPCertID, issuerNameHash) },
171
    { SEC_ASN1_OCTET_STRING,
172
      offsetof(CERTOCSPCertID, issuerKeyHash) },
173
    { SEC_ASN1_INTEGER,
174
      offsetof(CERTOCSPCertID, serialNumber) },
175
    { 0 }
176
};
177
178
static const SEC_ASN1Template myCERT_CertExtensionTemplate[] = {
179
    { SEC_ASN1_SEQUENCE,
180
      0, NULL, sizeof(CERTCertExtension) },
181
    { SEC_ASN1_OBJECT_ID,
182
      offsetof(CERTCertExtension, id) },
183
    { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */
184
      offsetof(CERTCertExtension, critical) },
185
    { SEC_ASN1_OCTET_STRING,
186
      offsetof(CERTCertExtension, value) },
187
    { 0 }
188
};
189
190
static const SEC_ASN1Template myCERT_SequenceOfCertExtensionTemplate[] = {
191
    { SEC_ASN1_SEQUENCE_OF, 0, myCERT_CertExtensionTemplate }
192
};
193
194
static const SEC_ASN1Template myCERT_PointerToSequenceOfCertExtensionTemplate[] = {
195
    { SEC_ASN1_POINTER, 0, myCERT_SequenceOfCertExtensionTemplate }
196
};
197
198
static const SEC_ASN1Template ocsp_mySingleResponseTemplate[] = {
199
    { SEC_ASN1_SEQUENCE,
200
      0, NULL, sizeof(CERTOCSPSingleResponse) },
201
    { SEC_ASN1_POINTER,
202
      offsetof(CERTOCSPSingleResponse, certID),
203
      ocsp_myCertIDTemplate },
204
    { SEC_ASN1_ANY,
205
      offsetof(CERTOCSPSingleResponse, derCertStatus) },
206
    { SEC_ASN1_GENERALIZED_TIME,
207
      offsetof(CERTOCSPSingleResponse, thisUpdate) },
208
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
209
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
210
      offsetof(CERTOCSPSingleResponse, nextUpdate),
211
      mySEC_PointerToGeneralizedTimeTemplate },
212
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
213
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
214
      offsetof(CERTOCSPSingleResponse, singleExtensions),
215
      myCERT_PointerToSequenceOfCertExtensionTemplate },
216
    { 0 }
217
};
218
219
static const SEC_ASN1Template ocsp_myResponseDataTemplate[] = {
220
    { SEC_ASN1_SEQUENCE,
221
      0, NULL, sizeof(ocspResponseData) },
222
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */
223
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
224
      offsetof(ocspResponseData, version),
225
      mySEC_PointerToIntegerTemplate },
226
    { SEC_ASN1_ANY,
227
      offsetof(ocspResponseData, derResponderID) },
228
    { SEC_ASN1_GENERALIZED_TIME,
229
      offsetof(ocspResponseData, producedAt) },
230
    { SEC_ASN1_SEQUENCE_OF,
231
      offsetof(ocspResponseData, responses),
232
      ocsp_mySingleResponseTemplate },
233
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
234
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
235
      offsetof(ocspResponseData, responseExtensions),
236
      myCERT_PointerToSequenceOfCertExtensionTemplate },
237
    { 0 }
238
};
239
240
static const SEC_ASN1Template ocsp_EncodeBasicOCSPResponseTemplate[] = {
241
    { SEC_ASN1_SEQUENCE,
242
      0, NULL, sizeof(ocspBasicOCSPResponse) },
243
    { SEC_ASN1_POINTER,
244
      offsetof(ocspBasicOCSPResponse, tbsResponseData),
245
      ocsp_myResponseDataTemplate },
246
    { SEC_ASN1_INLINE,
247
      offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm),
248
      mySECOID_AlgorithmIDTemplate },
249
    { SEC_ASN1_BIT_STRING,
250
      offsetof(ocspBasicOCSPResponse, responseSignature.signature) },
251
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
252
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
253
      offsetof(ocspBasicOCSPResponse, responseSignature.derCerts),
254
      mySEC_PointerToSequenceOfAnyTemplate },
255
    { 0 }
256
};
257
258
static CERTOCSPSingleResponse *
259
ocsp_CreateSingleResponse(PLArenaPool *arena,
260
                          CERTOCSPCertID *id, ocspCertStatus *status,
261
                          PRTime thisUpdate, const PRTime *nextUpdate)
262
0
{
263
0
    CERTOCSPSingleResponse *sr;
264
0
265
0
    if (!arena || !id || !status) {
266
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
267
0
        return NULL;
268
0
    }
269
0
270
0
    sr = PORT_ArenaZNew(arena, CERTOCSPSingleResponse);
271
0
    if (!sr)
272
0
        return NULL;
273
0
    sr->arena = arena;
274
0
    sr->certID = id;
275
0
    sr->certStatus = status;
276
0
    if (DER_TimeToGeneralizedTimeArena(arena, &sr->thisUpdate, thisUpdate) !=
277
0
        SECSuccess)
278
0
        return NULL;
279
0
    sr->nextUpdate = NULL;
280
0
    if (nextUpdate) {
281
0
        sr->nextUpdate = SECITEM_AllocItem(arena, NULL, 0);
282
0
        if (!sr->nextUpdate)
283
0
            return NULL;
284
0
        if (DER_TimeToGeneralizedTimeArena(arena, sr->nextUpdate, *nextUpdate) !=
285
0
            SECSuccess)
286
0
            return NULL;
287
0
    }
288
0
289
0
    sr->singleExtensions = PORT_ArenaNewArray(arena, CERTCertExtension *, 1);
290
0
    if (!sr->singleExtensions)
291
0
        return NULL;
292
0
293
0
    sr->singleExtensions[0] = NULL;
294
0
295
0
    if (!SEC_ASN1EncodeItem(arena, &sr->derCertStatus,
296
0
                            status, ocsp_CertStatusTemplate))
297
0
        return NULL;
298
0
299
0
    return sr;
300
0
}
301
302
CERTOCSPSingleResponse *
303
CERT_CreateOCSPSingleResponseGood(PLArenaPool *arena,
304
                                  CERTOCSPCertID *id,
305
                                  PRTime thisUpdate,
306
                                  const PRTime *nextUpdate)
307
0
{
308
0
    ocspCertStatus *cs;
309
0
    if (!arena) {
310
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
311
0
        return NULL;
312
0
    }
313
0
    cs = ocsp_CreateCertStatus(arena, ocspCertStatus_good, 0);
314
0
    if (!cs)
315
0
        return NULL;
316
0
    return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
317
0
}
318
319
CERTOCSPSingleResponse *
320
CERT_CreateOCSPSingleResponseUnknown(PLArenaPool *arena,
321
                                     CERTOCSPCertID *id,
322
                                     PRTime thisUpdate,
323
                                     const PRTime *nextUpdate)
324
0
{
325
0
    ocspCertStatus *cs;
326
0
    if (!arena) {
327
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
328
0
        return NULL;
329
0
    }
330
0
    cs = ocsp_CreateCertStatus(arena, ocspCertStatus_unknown, 0);
331
0
    if (!cs)
332
0
        return NULL;
333
0
    return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
334
0
}
335
336
CERTOCSPSingleResponse *
337
CERT_CreateOCSPSingleResponseRevoked(
338
    PLArenaPool *arena,
339
    CERTOCSPCertID *id,
340
    PRTime thisUpdate,
341
    const PRTime *nextUpdate,
342
    PRTime revocationTime,
343
    const CERTCRLEntryReasonCode *revocationReason)
344
0
{
345
0
    ocspCertStatus *cs;
346
0
    /* revocationReason is not yet supported, so it must be NULL. */
347
0
    if (!arena || revocationReason) {
348
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
349
0
        return NULL;
350
0
    }
351
0
    cs = ocsp_CreateCertStatus(arena, ocspCertStatus_revoked, revocationTime);
352
0
    if (!cs)
353
0
        return NULL;
354
0
    return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
355
0
}
356
357
/* responderCert == 0 means:
358
 * create a response with an invalid signature (for testing purposes) */
359
SECItem *
360
CERT_CreateEncodedOCSPSuccessResponse(
361
    PLArenaPool *arena,
362
    CERTCertificate *responderCert,
363
    CERTOCSPResponderIDType responderIDType,
364
    PRTime producedAt,
365
    CERTOCSPSingleResponse **responses,
366
    void *wincx)
367
0
{
368
0
    PLArenaPool *tmpArena;
369
0
    ocspResponseData *rd = NULL;
370
0
    ocspResponderID *rid = NULL;
371
0
    const SEC_ASN1Template *responderIDTemplate = NULL;
372
0
    ocspBasicOCSPResponse *br = NULL;
373
0
    ocspResponseBytes *rb = NULL;
374
0
    CERTOCSPResponse *response = NULL;
375
0
376
0
    SECOidTag algID;
377
0
    SECOidData *od = NULL;
378
0
    SECKEYPrivateKey *privKey = NULL;
379
0
    SECItem *result = NULL;
380
0
381
0
    if (!arena || !responses) {
382
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
383
0
        return NULL;
384
0
    }
385
0
    if (responderIDType != ocspResponderID_byName &&
386
0
        responderIDType != ocspResponderID_byKey) {
387
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
388
0
        return NULL;
389
0
    }
390
0
391
0
    tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
392
0
    if (!tmpArena)
393
0
        return NULL;
394
0
395
0
    rd = PORT_ArenaZNew(tmpArena, ocspResponseData);
396
0
    if (!rd)
397
0
        goto done;
398
0
    rid = PORT_ArenaZNew(tmpArena, ocspResponderID);
399
0
    if (!rid)
400
0
        goto done;
401
0
    br = PORT_ArenaZNew(tmpArena, ocspBasicOCSPResponse);
402
0
    if (!br)
403
0
        goto done;
404
0
    rb = PORT_ArenaZNew(tmpArena, ocspResponseBytes);
405
0
    if (!rb)
406
0
        goto done;
407
0
    response = PORT_ArenaZNew(tmpArena, CERTOCSPResponse);
408
0
    if (!response)
409
0
        goto done;
410
0
411
0
    rd->version.data = NULL;
412
0
    rd->version.len = 0;
413
0
    rd->responseExtensions = NULL;
414
0
    rd->responses = responses;
415
0
    if (DER_TimeToGeneralizedTimeArena(tmpArena, &rd->producedAt, producedAt) !=
416
0
        SECSuccess)
417
0
        goto done;
418
0
419
0
    if (!responderCert) {
420
0
        /* use invalid signature for testing purposes */
421
0
        unsigned char dummyChar = 'd';
422
0
        SECItem dummy;
423
0
424
0
        dummy.len = 1;
425
0
        dummy.data = &dummyChar;
426
0
427
0
        /* it's easier to produdce a keyHash out of nowhere,
428
0
       * than to produce an encoded subject,
429
0
       * so for our dummy response we always use byKey
430
0
       */
431
0
432
0
        rid->responderIDType = ocspResponderID_byKey;
433
0
        if (!ocsp_DigestValue(tmpArena, SEC_OID_SHA1, &rid->responderIDValue.keyHash,
434
0
                              &dummy))
435
0
            goto done;
436
0
437
0
        if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid,
438
0
                                ocsp_ResponderIDByKeyTemplate))
439
0
            goto done;
440
0
441
0
        br->tbsResponseData = rd;
442
0
443
0
        if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData,
444
0
                                ocsp_myResponseDataTemplate))
445
0
            goto done;
446
0
447
0
        br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem *, 1);
448
0
        if (!br->responseSignature.derCerts)
449
0
            goto done;
450
0
        br->responseSignature.derCerts[0] = NULL;
451
0
452
0
        algID = SEC_GetSignatureAlgorithmOidTag(rsaKey, SEC_OID_SHA1);
453
0
        if (algID == SEC_OID_UNKNOWN)
454
0
            goto done;
455
0
456
0
        /* match the regular signature code, which doesn't use the arena */
457
0
        if (!SECITEM_AllocItem(NULL, &br->responseSignature.signature, 1))
458
0
            goto done;
459
0
        PORT_Memcpy(br->responseSignature.signature.data, &dummyChar, 1);
460
0
461
0
        /* convert len-in-bytes to len-in-bits */
462
0
        br->responseSignature.signature.len = br->responseSignature.signature.len << 3;
463
0
    } else {
464
0
        rid->responderIDType = responderIDType;
465
0
        if (responderIDType == ocspResponderID_byName) {
466
0
            responderIDTemplate = ocsp_ResponderIDByNameTemplate;
467
0
            if (CERT_CopyName(tmpArena, &rid->responderIDValue.name,
468
0
                              &responderCert->subject) != SECSuccess)
469
0
                goto done;
470
0
        } else {
471
0
            responderIDTemplate = ocsp_ResponderIDByKeyTemplate;
472
0
            if (!CERT_GetSubjectPublicKeyDigest(tmpArena, responderCert,
473
0
                                                SEC_OID_SHA1, &rid->responderIDValue.keyHash))
474
0
                goto done;
475
0
        }
476
0
477
0
        if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid,
478
0
                                responderIDTemplate))
479
0
            goto done;
480
0
481
0
        br->tbsResponseData = rd;
482
0
483
0
        if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData,
484
0
                                ocsp_myResponseDataTemplate))
485
0
            goto done;
486
0
487
0
        br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem *, 1);
488
0
        if (!br->responseSignature.derCerts)
489
0
            goto done;
490
0
        br->responseSignature.derCerts[0] = NULL;
491
0
492
0
        privKey = PK11_FindKeyByAnyCert(responderCert, wincx);
493
0
        if (!privKey)
494
0
            goto done;
495
0
496
0
        algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1);
497
0
        if (algID == SEC_OID_UNKNOWN)
498
0
            goto done;
499
0
500
0
        if (SEC_SignData(&br->responseSignature.signature,
501
0
                         br->tbsResponseDataDER.data, br->tbsResponseDataDER.len,
502
0
                         privKey, algID) !=
503
0
            SECSuccess)
504
0
            goto done;
505
0
506
0
        /* convert len-in-bytes to len-in-bits */
507
0
        br->responseSignature.signature.len = br->responseSignature.signature.len << 3;
508
0
509
0
        /* br->responseSignature.signature wasn't allocated from arena,
510
0
       * we must free it when done. */
511
0
    }
512
0
513
0
    if (SECOID_SetAlgorithmID(tmpArena, &br->responseSignature.signatureAlgorithm, algID, 0) !=
514
0
        SECSuccess)
515
0
        goto done;
516
0
517
0
    if (!SEC_ASN1EncodeItem(tmpArena, &rb->response, br,
518
0
                            ocsp_EncodeBasicOCSPResponseTemplate))
519
0
        goto done;
520
0
521
0
    rb->responseTypeTag = SEC_OID_PKIX_OCSP_BASIC_RESPONSE;
522
0
523
0
    od = SECOID_FindOIDByTag(rb->responseTypeTag);
524
0
    if (!od)
525
0
        goto done;
526
0
527
0
    rb->responseType = od->oid;
528
0
    rb->decodedResponse.basic = br;
529
0
530
0
    response->arena = tmpArena;
531
0
    response->responseBytes = rb;
532
0
    response->statusValue = ocspResponse_successful;
533
0
534
0
    if (!SEC_ASN1EncodeInteger(tmpArena, &response->responseStatus,
535
0
                               response->statusValue))
536
0
        goto done;
537
0
538
0
    result = SEC_ASN1EncodeItem(arena, NULL, response, ocsp_OCSPResponseTemplate);
539
0
540
0
done:
541
0
    if (privKey)
542
0
        SECKEY_DestroyPrivateKey(privKey);
543
0
    if (br && br->responseSignature.signature.data)
544
0
        SECITEM_FreeItem(&br->responseSignature.signature, PR_FALSE);
545
0
    PORT_FreeArena(tmpArena, PR_FALSE);
546
0
547
0
    return result;
548
0
}
549
550
static const SEC_ASN1Template ocsp_OCSPErrorResponseTemplate[] = {
551
    { SEC_ASN1_SEQUENCE,
552
      0, NULL, sizeof(CERTOCSPResponse) },
553
    { SEC_ASN1_ENUMERATED,
554
      offsetof(CERTOCSPResponse, responseStatus) },
555
    { 0, 0,
556
      mySEC_NullTemplate },
557
    { 0 }
558
};
559
560
SECItem *
561
CERT_CreateEncodedOCSPErrorResponse(PLArenaPool *arena, int error)
562
0
{
563
0
    CERTOCSPResponse response;
564
0
    SECItem *result = NULL;
565
0
566
0
    switch (error) {
567
0
        case SEC_ERROR_OCSP_MALFORMED_REQUEST:
568
0
            response.statusValue = ocspResponse_malformedRequest;
569
0
            break;
570
0
        case SEC_ERROR_OCSP_SERVER_ERROR:
571
0
            response.statusValue = ocspResponse_internalError;
572
0
            break;
573
0
        case SEC_ERROR_OCSP_TRY_SERVER_LATER:
574
0
            response.statusValue = ocspResponse_tryLater;
575
0
            break;
576
0
        case SEC_ERROR_OCSP_REQUEST_NEEDS_SIG:
577
0
            response.statusValue = ocspResponse_sigRequired;
578
0
            break;
579
0
        case SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST:
580
0
            response.statusValue = ocspResponse_unauthorized;
581
0
            break;
582
0
        default:
583
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
584
0
            return NULL;
585
0
    }
586
0
587
0
    if (!SEC_ASN1EncodeInteger(NULL, &response.responseStatus,
588
0
                               response.statusValue))
589
0
        return NULL;
590
0
591
0
    result = SEC_ASN1EncodeItem(arena, NULL, &response,
592
0
                                ocsp_OCSPErrorResponseTemplate);
593
0
594
0
    SECITEM_FreeItem(&response.responseStatus, PR_FALSE);
595
0
596
0
    return result;
597
0
}