Coverage Report

Created: 2025-09-05 06:13

/src/boringssl/pki/ocsp.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2016 The Chromium Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "ocsp.h"
16
17
#include <openssl/bytestring.h>
18
#include <openssl/digest.h>
19
#include <openssl/mem.h>
20
#include <openssl/pool.h>
21
#include <openssl/sha.h>
22
#include <openssl/span.h>
23
24
#include "cert_errors.h"
25
#include "extended_key_usage.h"
26
#include "parsed_certificate.h"
27
#include "revocation_util.h"
28
#include "string_util.h"
29
#include "verify_name_match.h"
30
#include "verify_signed_data.h"
31
32
BSSL_NAMESPACE_BEGIN
33
34
872
OCSPCertID::OCSPCertID() = default;
35
872
OCSPCertID::~OCSPCertID() = default;
36
37
1.16k
OCSPSingleResponse::OCSPSingleResponse() = default;
38
1.16k
OCSPSingleResponse::~OCSPSingleResponse() = default;
39
40
1.13k
OCSPResponseData::OCSPResponseData() = default;
41
1.13k
OCSPResponseData::~OCSPResponseData() = default;
42
43
1.22k
OCSPResponse::OCSPResponse() = default;
44
1.22k
OCSPResponse::~OCSPResponse() = default;
45
46
// CertID ::= SEQUENCE {
47
//    hashAlgorithm           AlgorithmIdentifier,
48
//    issuerNameHash          OCTET STRING, -- Hash of issuer's DN
49
//    issuerKeyHash           OCTET STRING, -- Hash of issuer's public key
50
//    serialNumber            CertificateSerialNumber
51
// }
52
872
bool ParseOCSPCertID(der::Input raw_tlv, OCSPCertID *out) {
53
872
  der::Parser outer_parser(raw_tlv);
54
872
  der::Parser parser;
55
872
  if (!outer_parser.ReadSequence(&parser)) {
56
492
    return false;
57
492
  }
58
380
  if (outer_parser.HasMore()) {
59
64
    return false;
60
64
  }
61
62
316
  der::Input sigalg_tlv;
63
316
  if (!parser.ReadRawTLV(&sigalg_tlv)) {
64
5
    return false;
65
5
  }
66
311
  if (!ParseHashAlgorithm(sigalg_tlv, &out->hash_algorithm)) {
67
242
    return false;
68
242
  }
69
69
  if (!parser.ReadTag(CBS_ASN1_OCTETSTRING, &out->issuer_name_hash)) {
70
6
    return false;
71
6
  }
72
63
  if (!parser.ReadTag(CBS_ASN1_OCTETSTRING, &out->issuer_key_hash)) {
73
1
    return false;
74
1
  }
75
62
  if (!parser.ReadTag(CBS_ASN1_INTEGER, &out->serial_number)) {
76
6
    return false;
77
6
  }
78
56
  CertErrors errors;
79
56
  if (!VerifySerialNumber(out->serial_number, false /*warnings_only*/,
80
56
                          &errors)) {
81
21
    return false;
82
21
  }
83
84
35
  return !parser.HasMore();
85
56
}
86
87
namespace {
88
89
// Parses |raw_tlv| to extract an OCSP RevokedInfo (RFC 6960) and stores the
90
// result in the OCSPCertStatus |out|. Returns whether the parsing was
91
// successful.
92
//
93
// RevokedInfo ::= SEQUENCE {
94
//      revocationTime              GeneralizedTime,
95
//      revocationReason    [0]     EXPLICIT CRLReason OPTIONAL
96
// }
97
312
bool ParseRevokedInfo(der::Input raw_tlv, OCSPCertStatus *out) {
98
312
  der::Parser parser(raw_tlv);
99
312
  if (!parser.ReadGeneralizedTime(&(out->revocation_time))) {
100
54
    return false;
101
54
  }
102
103
258
  der::Input reason_input;
104
258
  if (!parser.ReadOptionalTag(
105
258
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, &reason_input,
106
258
          &(out->has_reason))) {
107
1
    return false;
108
1
  }
109
257
  if (out->has_reason) {
110
172
    der::Parser reason_parser(reason_input);
111
172
    der::Input reason_value_input;
112
172
    uint8_t reason_value;
113
172
    if (!reason_parser.ReadTag(CBS_ASN1_ENUMERATED, &reason_value_input)) {
114
3
      return false;
115
3
    }
116
169
    if (!der::ParseUint8(reason_value_input, &reason_value)) {
117
131
      return false;
118
131
    }
119
38
    if (reason_value >
120
38
        static_cast<uint8_t>(OCSPCertStatus::RevocationReason::LAST)) {
121
13
      return false;
122
13
    }
123
25
    out->revocation_reason =
124
25
        static_cast<OCSPCertStatus::RevocationReason>(reason_value);
125
25
    if (out->revocation_reason == OCSPCertStatus::RevocationReason::UNUSED) {
126
1
      return false;
127
1
    }
128
24
    if (reason_parser.HasMore()) {
129
1
      return false;
130
1
    }
131
24
  }
132
108
  return !parser.HasMore();
133
257
}
134
135
// Parses |raw_tlv| to extract an OCSP CertStatus (RFC 6960) and stores the
136
// result in the OCSPCertStatus |out|. Returns whether the parsing was
137
// successful.
138
//
139
// CertStatus ::= CHOICE {
140
//      good        [0]     IMPLICIT NULL,
141
//      revoked     [1]     IMPLICIT RevokedInfo,
142
//      unknown     [2]     IMPLICIT UnknownInfo
143
// }
144
//
145
// UnknownInfo ::= NULL
146
585
bool ParseCertStatus(der::Input raw_tlv, OCSPCertStatus *out) {
147
585
  der::Parser parser(raw_tlv);
148
585
  CBS_ASN1_TAG status_tag;
149
585
  der::Input status;
150
585
  if (!parser.ReadTagAndValue(&status_tag, &status)) {
151
0
    return false;
152
0
  }
153
154
585
  out->has_reason = false;
155
585
  if (status_tag == (CBS_ASN1_CONTEXT_SPECIFIC | 0)) {
156
113
    out->status = OCSPRevocationStatus::GOOD;
157
472
  } else if (status_tag ==
158
472
             (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
159
312
    out->status = OCSPRevocationStatus::REVOKED;
160
312
    if (!ParseRevokedInfo(status, out)) {
161
206
      return false;
162
206
    }
163
312
  } else if (status_tag == (CBS_ASN1_CONTEXT_SPECIFIC | 2)) {
164
50
    out->status = OCSPRevocationStatus::UNKNOWN;
165
110
  } else {
166
110
    return false;
167
110
  }
168
169
269
  return !parser.HasMore();
170
585
}
171
172
// Writes the hash of |value| as an OCTET STRING to |cbb|, using |hash_type| as
173
// the algorithm. Returns true on success.
174
bool AppendHashAsOctetString(const EVP_MD *hash_type, CBB *cbb,
175
0
                             der::Input value) {
176
0
  CBB octet_string;
177
0
  unsigned hash_len;
178
0
  uint8_t hash_buffer[EVP_MAX_MD_SIZE];
179
180
0
  return CBB_add_asn1(cbb, &octet_string, CBS_ASN1_OCTETSTRING) &&
181
0
         EVP_Digest(value.data(), value.size(), hash_buffer, &hash_len,
182
0
                    hash_type, nullptr) &&
183
0
         CBB_add_bytes(&octet_string, hash_buffer, hash_len) && CBB_flush(cbb);
184
0
}
185
186
}  // namespace
187
188
// SingleResponse ::= SEQUENCE {
189
//      certID                       CertID,
190
//      certStatus                   CertStatus,
191
//      thisUpdate                   GeneralizedTime,
192
//      nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
193
//      singleExtensions   [1]       EXPLICIT Extensions OPTIONAL
194
// }
195
1.16k
bool ParseOCSPSingleResponse(der::Input raw_tlv, OCSPSingleResponse *out) {
196
1.16k
  der::Parser outer_parser(raw_tlv);
197
1.16k
  der::Parser parser;
198
1.16k
  if (!outer_parser.ReadSequence(&parser)) {
199
503
    return false;
200
503
  }
201
664
  if (outer_parser.HasMore()) {
202
62
    return false;
203
62
  }
204
205
602
  if (!parser.ReadRawTLV(&(out->cert_id_tlv))) {
206
10
    return false;
207
10
  }
208
592
  der::Input status_tlv;
209
592
  if (!parser.ReadRawTLV(&status_tlv)) {
210
7
    return false;
211
7
  }
212
585
  if (!ParseCertStatus(status_tlv, &(out->cert_status))) {
213
316
    return false;
214
316
  }
215
269
  if (!parser.ReadGeneralizedTime(&(out->this_update))) {
216
160
    return false;
217
160
  }
218
219
109
  der::Input next_update_input;
220
109
  if (!parser.ReadOptionalTag(
221
109
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
222
109
          &next_update_input, &(out->has_next_update))) {
223
4
    return false;
224
4
  }
225
105
  if (out->has_next_update) {
226
40
    der::Parser next_update_parser(next_update_input);
227
40
    if (!next_update_parser.ReadGeneralizedTime(&(out->next_update))) {
228
19
      return false;
229
19
    }
230
21
    if (next_update_parser.HasMore()) {
231
2
      return false;
232
2
    }
233
21
  }
234
235
84
  if (!parser.ReadOptionalTag(
236
84
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1,
237
84
          &(out->extensions), &(out->has_extensions))) {
238
1
    return false;
239
1
  }
240
241
83
  return !parser.HasMore();
242
84
}
243
244
namespace {
245
246
// Parses |raw_tlv| to extract a ResponderID (RFC 6960) and stores the
247
// result in the ResponderID |out|. Returns whether the parsing was successful.
248
//
249
// ResponderID ::= CHOICE {
250
//      byName               [1] Name,
251
//      byKey                [2] KeyHash
252
// }
253
387
bool ParseResponderID(der::Input raw_tlv, OCSPResponseData::ResponderID *out) {
254
387
  der::Parser parser(raw_tlv);
255
387
  CBS_ASN1_TAG id_tag;
256
387
  der::Input id_input;
257
387
  if (!parser.ReadTagAndValue(&id_tag, &id_input)) {
258
0
    return false;
259
0
  }
260
261
387
  if (id_tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
262
246
    out->type = OCSPResponseData::ResponderType::NAME;
263
246
    out->name = id_input;
264
246
  } else if (id_tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 2)) {
265
24
    der::Parser key_parser(id_input);
266
24
    der::Input key_hash;
267
24
    if (!key_parser.ReadTag(CBS_ASN1_OCTETSTRING, &key_hash)) {
268
6
      return false;
269
6
    }
270
18
    if (key_parser.HasMore()) {
271
1
      return false;
272
1
    }
273
17
    if (key_hash.size() != SHA_DIGEST_LENGTH) {
274
12
      return false;
275
12
    }
276
277
5
    out->type = OCSPResponseData::ResponderType::KEY_HASH;
278
5
    out->key_hash = key_hash;
279
117
  } else {
280
117
    return false;
281
117
  }
282
251
  return !parser.HasMore();
283
387
}
284
285
}  // namespace
286
287
// ResponseData ::= SEQUENCE {
288
//      version              [0] EXPLICIT Version DEFAULT v1,
289
//      responderID              ResponderID,
290
//      producedAt               GeneralizedTime,
291
//      responses                SEQUENCE OF SingleResponse,
292
//      responseExtensions   [1] EXPLICIT Extensions OPTIONAL
293
// }
294
1.13k
bool ParseOCSPResponseData(der::Input raw_tlv, OCSPResponseData *out) {
295
1.13k
  der::Parser outer_parser(raw_tlv);
296
1.13k
  der::Parser parser;
297
1.13k
  if (!outer_parser.ReadSequence(&parser)) {
298
491
    return false;
299
491
  }
300
640
  if (outer_parser.HasMore()) {
301
62
    return false;
302
62
  }
303
304
578
  der::Input version_input;
305
578
  bool version_present;
306
578
  if (!parser.ReadOptionalTag(
307
578
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, &version_input,
308
578
          &version_present)) {
309
11
    return false;
310
11
  }
311
312
  // For compatibilty, we ignore the restriction from X.690 Section 11.5 that
313
  // DEFAULT values should be omitted for values equal to the default value.
314
  // TODO: Add warning about non-strict parsing.
315
567
  if (version_present) {
316
191
    der::Parser version_parser(version_input);
317
191
    if (!version_parser.ReadUint8(&(out->version))) {
318
164
      return false;
319
164
    }
320
27
    if (version_parser.HasMore()) {
321
1
      return false;
322
1
    }
323
376
  } else {
324
376
    out->version = 0;
325
376
  }
326
327
402
  if (out->version != 0) {
328
12
    return false;
329
12
  }
330
331
390
  der::Input responder_input;
332
390
  if (!parser.ReadRawTLV(&responder_input)) {
333
3
    return false;
334
3
  }
335
387
  if (!ParseResponderID(responder_input, &(out->responder_id))) {
336
136
    return false;
337
136
  }
338
251
  if (!parser.ReadGeneralizedTime(&(out->produced_at))) {
339
159
    return false;
340
159
  }
341
342
92
  der::Parser responses_parser;
343
92
  if (!parser.ReadSequence(&responses_parser)) {
344
28
    return false;
345
28
  }
346
64
  out->responses.clear();
347
20.5k
  while (responses_parser.HasMore()) {
348
20.4k
    der::Input single_response;
349
20.4k
    if (!responses_parser.ReadRawTLV(&single_response)) {
350
27
      return false;
351
27
    }
352
20.4k
    out->responses.push_back(single_response);
353
20.4k
  }
354
355
37
  if (!parser.ReadOptionalTag(
356
37
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1,
357
37
          &(out->extensions), &(out->has_extensions))) {
358
6
    return false;
359
6
  }
360
361
31
  return !parser.HasMore();
362
37
}
363
364
namespace {
365
366
// Parses |raw_tlv| to extract a BasicOCSPResponse (RFC 6960) and stores the
367
// result in the OCSPResponse |out|. Returns whether the parsing was
368
// successful.
369
//
370
// BasicOCSPResponse       ::= SEQUENCE {
371
//      tbsResponseData      ResponseData,
372
//      signatureAlgorithm   AlgorithmIdentifier,
373
//      signature            BIT STRING,
374
//      certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
375
// }
376
327
bool ParseBasicOCSPResponse(der::Input raw_tlv, OCSPResponse *out) {
377
327
  der::Parser outer_parser(raw_tlv);
378
327
  der::Parser parser;
379
327
  if (!outer_parser.ReadSequence(&parser)) {
380
1
    return false;
381
1
  }
382
326
  if (outer_parser.HasMore()) {
383
1
    return false;
384
1
  }
385
386
325
  if (!parser.ReadRawTLV(&(out->data))) {
387
3
    return false;
388
3
  }
389
322
  der::Input sigalg_tlv;
390
322
  if (!parser.ReadRawTLV(&sigalg_tlv)) {
391
3
    return false;
392
3
  }
393
  // TODO(crbug.com/634443): Propagate the errors.
394
319
  std::optional<SignatureAlgorithm> sigalg =
395
319
      ParseSignatureAlgorithm(sigalg_tlv);
396
319
  if (!sigalg) {
397
190
    return false;
398
190
  }
399
129
  out->signature_algorithm = sigalg.value();
400
129
  std::optional<der::BitString> signature = parser.ReadBitString();
401
129
  if (!signature) {
402
26
    return false;
403
26
  }
404
103
  out->signature = signature.value();
405
103
  der::Input certs_input;
406
103
  if (!parser.ReadOptionalTag(
407
103
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, &certs_input,
408
103
          &(out->has_certs))) {
409
6
    return false;
410
6
  }
411
412
97
  out->certs.clear();
413
97
  if (out->has_certs) {
414
33
    der::Parser certs_seq_parser(certs_input);
415
33
    der::Parser certs_parser;
416
33
    if (!certs_seq_parser.ReadSequence(&certs_parser)) {
417
7
      return false;
418
7
    }
419
26
    if (certs_seq_parser.HasMore()) {
420
2
      return false;
421
2
    }
422
1.35k
    while (certs_parser.HasMore()) {
423
1.34k
      der::Input cert_tlv;
424
1.34k
      if (!certs_parser.ReadRawTLV(&cert_tlv)) {
425
15
        return false;
426
15
      }
427
1.32k
      out->certs.push_back(cert_tlv);
428
1.32k
    }
429
24
  }
430
431
73
  return !parser.HasMore();
432
97
}
433
434
}  // namespace
435
436
// OCSPResponse ::= SEQUENCE {
437
//      responseStatus         OCSPResponseStatus,
438
//      responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL
439
// }
440
//
441
// ResponseBytes ::=       SEQUENCE {
442
//      responseType   OBJECT IDENTIFIER,
443
//      response       OCTET STRING
444
// }
445
1.22k
bool ParseOCSPResponse(der::Input raw_tlv, OCSPResponse *out) {
446
1.22k
  der::Parser outer_parser(raw_tlv);
447
1.22k
  der::Parser parser;
448
1.22k
  if (!outer_parser.ReadSequence(&parser)) {
449
530
    return false;
450
530
  }
451
691
  if (outer_parser.HasMore()) {
452
62
    return false;
453
62
  }
454
455
629
  der::Input response_status_input;
456
629
  uint8_t response_status;
457
629
  if (!parser.ReadTag(CBS_ASN1_ENUMERATED, &response_status_input)) {
458
13
    return false;
459
13
  }
460
616
  if (!der::ParseUint8(response_status_input, &response_status)) {
461
168
    return false;
462
168
  }
463
448
  if (response_status >
464
448
      static_cast<uint8_t>(OCSPResponse::ResponseStatus::LAST)) {
465
15
    return false;
466
15
  }
467
433
  out->status = static_cast<OCSPResponse::ResponseStatus>(response_status);
468
433
  if (out->status == OCSPResponse::ResponseStatus::UNUSED) {
469
1
    return false;
470
1
  }
471
472
432
  if (out->status == OCSPResponse::ResponseStatus::SUCCESSFUL) {
473
427
    der::Parser outer_bytes_parser;
474
427
    der::Parser bytes_parser;
475
427
    if (!parser.ReadConstructed(
476
427
            CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
477
427
            &outer_bytes_parser)) {
478
2
      return false;
479
2
    }
480
425
    if (!outer_bytes_parser.ReadSequence(&bytes_parser)) {
481
3
      return false;
482
3
    }
483
422
    if (outer_bytes_parser.HasMore()) {
484
1
      return false;
485
1
    }
486
487
421
    der::Input type_oid;
488
421
    if (!bytes_parser.ReadTag(CBS_ASN1_OBJECT, &type_oid)) {
489
2
      return false;
490
2
    }
491
419
    if (type_oid != der::Input(kBasicOCSPResponseOid)) {
492
91
      return false;
493
91
    }
494
495
    // As per RFC 6960 Section 4.2.1, the value of |response| SHALL be the DER
496
    // encoding of BasicOCSPResponse.
497
328
    der::Input response;
498
328
    if (!bytes_parser.ReadTag(CBS_ASN1_OCTETSTRING, &response)) {
499
1
      return false;
500
1
    }
501
327
    if (!ParseBasicOCSPResponse(response, out)) {
502
318
      return false;
503
318
    }
504
9
    if (bytes_parser.HasMore()) {
505
1
      return false;
506
1
    }
507
9
  }
508
509
13
  return !parser.HasMore();
510
432
}
511
512
namespace {
513
514
// Checks that the |type| hash of |value| is equal to |hash|
515
0
bool VerifyHash(const EVP_MD *type, der::Input hash, der::Input value) {
516
0
  unsigned value_hash_len;
517
0
  uint8_t value_hash[EVP_MAX_MD_SIZE];
518
0
  if (!EVP_Digest(value.data(), value.size(), value_hash, &value_hash_len, type,
519
0
                  nullptr)) {
520
0
    return false;
521
0
  }
522
523
0
  return hash == der::Input(value_hash, value_hash_len);
524
0
}
525
526
// Extracts the bytes of the SubjectPublicKey bit string given an SPKI. That is
527
// to say, the value of subjectPublicKey without the leading unused bit
528
// count octet.
529
//
530
// Returns true on success and fills |*spk_tlv| with the result.
531
//
532
// From RFC 5280, Section 4.1
533
//   SubjectPublicKeyInfo  ::=  SEQUENCE  {
534
//     algorithm            AlgorithmIdentifier,
535
//     subjectPublicKey     BIT STRING  }
536
//
537
//   AlgorithmIdentifier  ::=  SEQUENCE  {
538
//     algorithm               OBJECT IDENTIFIER,
539
//     parameters              ANY DEFINED BY algorithm OPTIONAL  }
540
//
541
0
bool GetSubjectPublicKeyBytes(der::Input spki_tlv, der::Input *spk_tlv) {
542
0
  CBS outer, inner, alg, spk;
543
0
  uint8_t unused_bit_count;
544
0
  CBS_init(&outer, spki_tlv.data(), spki_tlv.size());
545
  //   The subjectPublicKey field includes the unused bit count. For this
546
  //   application, the unused bit count must be zero, and is not included in
547
  //   the result. We extract the subjectPubicKey bit string, verify the first
548
  //   byte is 0, and if so set |spk_tlv| to the remaining bytes.
549
0
  if (!CBS_get_asn1(&outer, &inner, CBS_ASN1_SEQUENCE) ||
550
0
      !CBS_get_asn1(&inner, &alg, CBS_ASN1_SEQUENCE) ||
551
0
      !CBS_get_asn1(&inner, &spk, CBS_ASN1_BITSTRING) ||
552
0
      !CBS_get_u8(&spk, &unused_bit_count) || unused_bit_count != 0) {
553
0
    return false;
554
0
  }
555
0
  *spk_tlv = der::Input(CBS_data(&spk), CBS_len(&spk));
556
0
  return true;
557
0
}
558
559
// Checks the OCSPCertID |id| identifies |certificate|.
560
bool CheckCertIDMatchesCertificate(
561
    const OCSPCertID &id, const ParsedCertificate *certificate,
562
0
    const ParsedCertificate *issuer_certificate) {
563
0
  const EVP_MD *type = nullptr;
564
0
  switch (id.hash_algorithm) {
565
0
    case DigestAlgorithm::Md2:
566
0
    case DigestAlgorithm::Md4:
567
0
    case DigestAlgorithm::Md5:
568
      // Unsupported.
569
0
      return false;
570
0
    case DigestAlgorithm::Sha1:
571
0
      type = EVP_sha1();
572
0
      break;
573
0
    case DigestAlgorithm::Sha256:
574
0
      type = EVP_sha256();
575
0
      break;
576
0
    case DigestAlgorithm::Sha384:
577
0
      type = EVP_sha384();
578
0
      break;
579
0
    case DigestAlgorithm::Sha512:
580
0
      type = EVP_sha512();
581
0
      break;
582
0
  }
583
584
0
  if (!VerifyHash(type, id.issuer_name_hash, certificate->tbs().issuer_tlv)) {
585
0
    return false;
586
0
  }
587
588
0
  der::Input key_tlv;
589
0
  if (!GetSubjectPublicKeyBytes(issuer_certificate->tbs().spki_tlv, &key_tlv)) {
590
0
    return false;
591
0
  }
592
593
0
  if (!VerifyHash(type, id.issuer_key_hash, key_tlv)) {
594
0
    return false;
595
0
  }
596
597
0
  return id.serial_number == certificate->tbs().serial_number;
598
0
}
599
600
// TODO(eroman): Revisit how certificate parsing is used by this file. Ideally
601
// would either pass in the parsed bits, or have a better abstraction for lazily
602
// parsing.
603
std::shared_ptr<const ParsedCertificate> OCSPParseCertificate(
604
0
    std::string_view der) {
605
0
  ParseCertificateOptions parse_options;
606
0
  parse_options.allow_invalid_serial_numbers = true;
607
608
  // The objects returned by this function only last for the duration of a
609
  // single certificate verification, so there is no need to pool them to save
610
  // memory.
611
  //
612
  // TODO(eroman): Swallows the parsing errors. However uses a permissive
613
  // parsing model.
614
0
  CertErrors errors;
615
0
  return ParsedCertificate::Create(
616
0
      bssl::UniquePtr<CRYPTO_BUFFER>(CRYPTO_BUFFER_new(
617
0
          reinterpret_cast<const uint8_t *>(der.data()), der.size(), nullptr)),
618
0
      {}, &errors);
619
0
}
620
621
// Checks that the ResponderID |id| matches the certificate |cert| either
622
// by verifying the name matches that of the certificate or that the hash
623
// matches the certificate's public key hash (RFC 6960, 4.2.2.3).
624
[[nodiscard]] bool CheckResponderIDMatchesCertificate(
625
0
    const OCSPResponseData::ResponderID &id, const ParsedCertificate *cert) {
626
0
  switch (id.type) {
627
0
    case OCSPResponseData::ResponderType::NAME: {
628
0
      der::Input name_rdn;
629
0
      der::Input cert_rdn;
630
0
      if (!der::Parser(id.name).ReadTag(CBS_ASN1_SEQUENCE, &name_rdn) ||
631
0
          !der::Parser(cert->tbs().subject_tlv)
632
0
               .ReadTag(CBS_ASN1_SEQUENCE, &cert_rdn)) {
633
0
        return false;
634
0
      }
635
0
      return VerifyNameMatch(name_rdn, cert_rdn);
636
0
    }
637
0
    case OCSPResponseData::ResponderType::KEY_HASH: {
638
0
      der::Input key;
639
0
      if (!GetSubjectPublicKeyBytes(cert->tbs().spki_tlv, &key)) {
640
0
        return false;
641
0
      }
642
0
      return VerifyHash(EVP_sha1(), id.key_hash, key);
643
0
    }
644
0
  }
645
646
0
  return false;
647
0
}
648
649
// Verifies that |responder_certificate| has been authority for OCSP signing,
650
// delegated to it by |issuer_certificate|.
651
//
652
// TODO(eroman): No revocation checks are done (see id-pkix-ocsp-nocheck in the
653
//     spec). extension).
654
//
655
// TODO(eroman): Not all properties of the certificate are verified, only the
656
//     signature and EKU. Can full RFC 5280 validation be used, or are there
657
//     compatibility concerns?
658
[[nodiscard]] bool VerifyAuthorizedResponderCert(
659
    const ParsedCertificate *responder_certificate,
660
0
    const ParsedCertificate *issuer_certificate) {
661
  // The Authorized Responder must be directly signed by the issuer of the
662
  // certificate being checked.
663
  // TODO(eroman): Must check the signature algorithm against policy.
664
0
  if (!responder_certificate->signature_algorithm().has_value() ||
665
0
      !VerifySignedData(*responder_certificate->signature_algorithm(),
666
0
                        responder_certificate->tbs_certificate_tlv(),
667
0
                        responder_certificate->signature_value(),
668
0
                        issuer_certificate->tbs().spki_tlv,
669
0
                        /*cache=*/nullptr)) {
670
0
    return false;
671
0
  }
672
673
  // The Authorized Responder must include the value id-kp-OCSPSigning as
674
  // part of the extended key usage extension.
675
0
  if (!responder_certificate->has_extended_key_usage()) {
676
0
    return false;
677
0
  }
678
679
0
  for (const auto &key_purpose_oid :
680
0
       responder_certificate->extended_key_usage()) {
681
0
    if (key_purpose_oid == der::Input(kOCSPSigning)) {
682
0
      return true;
683
0
    }
684
0
  }
685
0
  return false;
686
0
}
687
688
[[nodiscard]] bool VerifyOCSPResponseSignatureGivenCert(
689
0
    const OCSPResponse &response, const ParsedCertificate *cert) {
690
  // TODO(eroman): Must check the signature algorithm against policy.
691
0
  return VerifySignedData(response.signature_algorithm, response.data,
692
0
                          response.signature, cert->tbs().spki_tlv,
693
0
                          /*cache=*/nullptr);
694
0
}
695
696
// Verifies that the OCSP response has a valid signature using
697
// |issuer_certificate|, or an authorized responder issued by
698
// |issuer_certificate| for OCSP signing.
699
[[nodiscard]] bool VerifyOCSPResponseSignature(
700
    const OCSPResponse &response, const OCSPResponseData &response_data,
701
0
    const ParsedCertificate *issuer_certificate) {
702
  // In order to verify the OCSP signature, a valid responder matching the OCSP
703
  // Responder ID must be located (RFC 6960, 4.2.2.2). The responder is allowed
704
  // to be either the certificate issuer or a delegated authority directly
705
  // signed by the issuer.
706
0
  if (CheckResponderIDMatchesCertificate(response_data.responder_id,
707
0
                                         issuer_certificate) &&
708
0
      VerifyOCSPResponseSignatureGivenCert(response, issuer_certificate)) {
709
0
    return true;
710
0
  }
711
712
  // Otherwise search through the provided certificates for the Authorized
713
  // Responder. Want a certificate that:
714
  //  (1) Matches the OCSP Responder ID.
715
  //  (2) Has been given authority for OCSP signing by |issuer_certificate|.
716
  //  (3) Has signed the OCSP response using its public key.
717
0
  for (const auto &responder_cert_tlv : response.certs) {
718
0
    std::shared_ptr<const ParsedCertificate> cur_responder_certificate =
719
0
        OCSPParseCertificate(BytesAsStringView(responder_cert_tlv));
720
721
    // If failed parsing the certificate, keep looking.
722
0
    if (!cur_responder_certificate) {
723
0
      continue;
724
0
    }
725
726
    // If the certificate doesn't match the OCSP's responder ID, keep looking.
727
0
    if (!CheckResponderIDMatchesCertificate(response_data.responder_id,
728
0
                                            cur_responder_certificate.get())) {
729
0
      continue;
730
0
    }
731
732
    // If the certificate isn't a valid Authorized Responder certificate, keep
733
    // looking.
734
0
    if (!VerifyAuthorizedResponderCert(cur_responder_certificate.get(),
735
0
                                       issuer_certificate)) {
736
0
      continue;
737
0
    }
738
739
    // If the certificate signed this OCSP response, have found a match.
740
    // Otherwise keep looking.
741
0
    if (VerifyOCSPResponseSignatureGivenCert(response,
742
0
                                             cur_responder_certificate.get())) {
743
0
      return true;
744
0
    }
745
0
  }
746
747
  // Failed to confirm the validity of the OCSP signature using any of the
748
  // candidate certificates.
749
0
  return false;
750
0
}
751
752
// Parse ResponseData and return false if any unhandled critical extensions are
753
// found. No known critical ResponseData extensions exist.
754
bool ParseOCSPResponseDataExtensions(
755
    der::Input response_extensions,
756
0
    OCSPVerifyResult::ResponseStatus *response_details) {
757
0
  std::map<der::Input, ParsedExtension> extensions;
758
0
  if (!ParseExtensions(response_extensions, &extensions)) {
759
0
    *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
760
0
    return false;
761
0
  }
762
763
0
  for (const auto &ext : extensions) {
764
    // TODO: handle ResponseData extensions
765
766
0
    if (ext.second.critical) {
767
0
      *response_details = OCSPVerifyResult::UNHANDLED_CRITICAL_EXTENSION;
768
0
      return false;
769
0
    }
770
0
  }
771
772
0
  return true;
773
0
}
774
775
// Parse SingleResponse and return false if any unhandled critical extensions
776
// (other than the CT extension) are found. The CT-SCT extension is not required
777
// to be marked critical, but since it is handled by Chrome, we will overlook
778
// the flag setting.
779
bool ParseOCSPSingleResponseExtensions(
780
    der::Input single_extensions,
781
0
    OCSPVerifyResult::ResponseStatus *response_details) {
782
0
  std::map<der::Input, ParsedExtension> extensions;
783
0
  if (!ParseExtensions(single_extensions, &extensions)) {
784
0
    *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
785
0
    return false;
786
0
  }
787
788
  // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for
789
  // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see
790
  // Section 3.3 of RFC6962.
791
0
  const uint8_t ct_ocsp_ext_oid[] = {0x2B, 0x06, 0x01, 0x04, 0x01,
792
0
                                     0xD6, 0x79, 0x02, 0x04, 0x05};
793
0
  der::Input ct_ext_oid(ct_ocsp_ext_oid);
794
795
0
  for (const auto &ext : extensions) {
796
    // The CT OCSP extension is handled in ct::ExtractSCTListFromOCSPResponse
797
0
    if (ext.second.oid == ct_ext_oid) {
798
0
      continue;
799
0
    }
800
801
    // TODO: handle SingleResponse extensions
802
803
0
    if (ext.second.critical) {
804
0
      *response_details = OCSPVerifyResult::UNHANDLED_CRITICAL_EXTENSION;
805
0
      return false;
806
0
    }
807
0
  }
808
809
0
  return true;
810
0
}
811
812
// Loops through the OCSPSingleResponses to find the best match for |cert|.
813
OCSPRevocationStatus GetRevocationStatusForCert(
814
    const OCSPResponseData &response_data, const ParsedCertificate *cert,
815
    const ParsedCertificate *issuer_certificate,
816
    int64_t verify_time_epoch_seconds, std::optional<int64_t> max_age_seconds,
817
0
    OCSPVerifyResult::ResponseStatus *response_details) {
818
0
  OCSPRevocationStatus result = OCSPRevocationStatus::UNKNOWN;
819
0
  *response_details = OCSPVerifyResult::NO_MATCHING_RESPONSE;
820
821
0
  for (const auto &single_response_der : response_data.responses) {
822
    // In the common case, there should only be one SingleResponse in the
823
    // ResponseData (matching the certificate requested and used on this
824
    // connection). However, it is possible for the OCSP responder to provide
825
    // multiple responses for multiple certificates. Look through all the
826
    // provided SingleResponses, and check to see if any match the
827
    // certificate. A SingleResponse matches a certificate if it has the same
828
    // serial number, issuer name (hash), and issuer public key (hash).
829
0
    OCSPSingleResponse single_response;
830
0
    if (!ParseOCSPSingleResponse(single_response_der, &single_response)) {
831
0
      return OCSPRevocationStatus::UNKNOWN;
832
0
    }
833
834
    // Reject unhandled critical extensions in SingleResponse
835
0
    if (single_response.has_extensions &&
836
0
        !ParseOCSPSingleResponseExtensions(single_response.extensions,
837
0
                                           response_details)) {
838
0
      return OCSPRevocationStatus::UNKNOWN;
839
0
    }
840
841
0
    OCSPCertID cert_id;
842
0
    if (!ParseOCSPCertID(single_response.cert_id_tlv, &cert_id)) {
843
0
      return OCSPRevocationStatus::UNKNOWN;
844
0
    }
845
0
    if (!CheckCertIDMatchesCertificate(cert_id, cert, issuer_certificate)) {
846
0
      continue;
847
0
    }
848
849
    // The SingleResponse matches the certificate, but may be out of date. Out
850
    // of date responses are noted seperate from responses with mismatched
851
    // serial numbers. If an OCSP responder provides both an up to date
852
    // response and an expired response, the up to date response takes
853
    // precedence (PROVIDED > INVALID_DATE).
854
0
    if (!CheckRevocationDateValid(single_response.this_update,
855
0
                                  single_response.has_next_update
856
0
                                      ? &single_response.next_update
857
0
                                      : nullptr,
858
0
                                  verify_time_epoch_seconds, max_age_seconds)) {
859
0
      if (*response_details != OCSPVerifyResult::PROVIDED) {
860
0
        *response_details = OCSPVerifyResult::INVALID_DATE;
861
0
      }
862
0
      continue;
863
0
    }
864
865
    // In the case with multiple matching and up to date responses, keep only
866
    // the strictest status (REVOKED > UNKNOWN > GOOD).
867
0
    if (*response_details != OCSPVerifyResult::PROVIDED ||
868
0
        result == OCSPRevocationStatus::GOOD ||
869
0
        single_response.cert_status.status == OCSPRevocationStatus::REVOKED) {
870
0
      result = single_response.cert_status.status;
871
0
    }
872
0
    *response_details = OCSPVerifyResult::PROVIDED;
873
0
  }
874
875
0
  return result;
876
0
}
877
878
OCSPRevocationStatus CheckOCSP(
879
    std::string_view raw_response, std::string_view certificate_der,
880
    const ParsedCertificate *certificate,
881
    std::string_view issuer_certificate_der,
882
    const ParsedCertificate *issuer_certificate,
883
    int64_t verify_time_epoch_seconds, std::optional<int64_t> max_age_seconds,
884
0
    OCSPVerifyResult::ResponseStatus *response_details) {
885
0
  *response_details = OCSPVerifyResult::NOT_CHECKED;
886
887
0
  if (raw_response.empty()) {
888
0
    *response_details = OCSPVerifyResult::MISSING;
889
0
    return OCSPRevocationStatus::UNKNOWN;
890
0
  }
891
892
0
  OCSPResponse response;
893
0
  if (!ParseOCSPResponse(StringAsBytes(raw_response), &response)) {
894
0
    *response_details = OCSPVerifyResult::PARSE_RESPONSE_ERROR;
895
0
    return OCSPRevocationStatus::UNKNOWN;
896
0
  }
897
898
  // RFC 6960 defines all responses |response_status| != SUCCESSFUL as error
899
  // responses. No revocation information is provided on error responses, and
900
  // the OCSPResponseData structure is not set.
901
0
  if (response.status != OCSPResponse::ResponseStatus::SUCCESSFUL) {
902
0
    *response_details = OCSPVerifyResult::ERROR_RESPONSE;
903
0
    return OCSPRevocationStatus::UNKNOWN;
904
0
  }
905
906
  // Actual revocation information is contained within the BasicOCSPResponse as
907
  // a ResponseData structure. The BasicOCSPResponse was parsed above, and
908
  // contains an unparsed ResponseData. From RFC 6960:
909
  //
910
  // BasicOCSPResponse       ::= SEQUENCE {
911
  //    tbsResponseData      ResponseData,
912
  //    signatureAlgorithm   AlgorithmIdentifier,
913
  //    signature            BIT STRING,
914
  //    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
915
  //
916
  // ResponseData ::= SEQUENCE {
917
  //     version              [0] EXPLICIT Version DEFAULT v1,
918
  //     responderID              ResponderID,
919
  //     producedAt               GeneralizedTime,
920
  //     responses                SEQUENCE OF SingleResponse,
921
  //     responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
922
0
  OCSPResponseData response_data;
923
0
  if (!ParseOCSPResponseData(response.data, &response_data)) {
924
0
    *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
925
0
    return OCSPRevocationStatus::UNKNOWN;
926
0
  }
927
928
  // Process the OCSP ResponseData extensions. In particular, must reject if
929
  // there are any critical extensions that are not understood.
930
0
  if (response_data.has_extensions &&
931
0
      !ParseOCSPResponseDataExtensions(response_data.extensions,
932
0
                                       response_details)) {
933
0
    return OCSPRevocationStatus::UNKNOWN;
934
0
  }
935
936
0
  std::shared_ptr<const ParsedCertificate> parsed_certificate;
937
0
  std::shared_ptr<const ParsedCertificate> parsed_issuer_certificate;
938
0
  if (!certificate) {
939
0
    parsed_certificate = OCSPParseCertificate(certificate_der);
940
0
    certificate = parsed_certificate.get();
941
0
  }
942
0
  if (!issuer_certificate) {
943
0
    parsed_issuer_certificate = OCSPParseCertificate(issuer_certificate_der);
944
0
    issuer_certificate = parsed_issuer_certificate.get();
945
0
  }
946
947
0
  if (!certificate || !issuer_certificate) {
948
0
    *response_details = OCSPVerifyResult::NOT_CHECKED;
949
0
    return OCSPRevocationStatus::UNKNOWN;
950
0
  }
951
952
  // If producedAt is outside of the certificate validity period, reject the
953
  // response.
954
0
  if (response_data.produced_at < certificate->tbs().validity_not_before ||
955
0
      response_data.produced_at > certificate->tbs().validity_not_after) {
956
0
    *response_details = OCSPVerifyResult::BAD_PRODUCED_AT;
957
0
    return OCSPRevocationStatus::UNKNOWN;
958
0
  }
959
960
  // Look through all of the OCSPSingleResponses for a match (based on CertID
961
  // and time).
962
0
  OCSPRevocationStatus status = GetRevocationStatusForCert(
963
0
      response_data, certificate, issuer_certificate, verify_time_epoch_seconds,
964
0
      max_age_seconds, response_details);
965
966
  // Check that the OCSP response has a valid signature. It must either be
967
  // signed directly by the issuing certificate, or a valid authorized
968
  // responder.
969
0
  if (!VerifyOCSPResponseSignature(response, response_data,
970
0
                                   issuer_certificate)) {
971
0
    return OCSPRevocationStatus::UNKNOWN;
972
0
  }
973
974
0
  return status;
975
0
}
976
977
}  // namespace
978
979
OCSPRevocationStatus CheckOCSP(
980
    std::string_view raw_response, std::string_view certificate_der,
981
    std::string_view issuer_certificate_der, int64_t verify_time_epoch_seconds,
982
    std::optional<int64_t> max_age_seconds,
983
0
    OCSPVerifyResult::ResponseStatus *response_details) {
984
0
  return CheckOCSP(raw_response, certificate_der, nullptr,
985
0
                   issuer_certificate_der, nullptr, verify_time_epoch_seconds,
986
0
                   max_age_seconds, response_details);
987
0
}
988
989
OCSPRevocationStatus CheckOCSP(
990
    std::string_view raw_response, const ParsedCertificate *certificate,
991
    const ParsedCertificate *issuer_certificate,
992
    int64_t verify_time_epoch_seconds, std::optional<int64_t> max_age_seconds,
993
0
    OCSPVerifyResult::ResponseStatus *response_details) {
994
0
  return CheckOCSP(raw_response, std::string_view(), certificate,
995
0
                   std::string_view(), issuer_certificate,
996
0
                   verify_time_epoch_seconds, max_age_seconds,
997
0
                   response_details);
998
0
}
999
1000
bool CreateOCSPRequest(const ParsedCertificate *cert,
1001
                       const ParsedCertificate *issuer,
1002
0
                       std::vector<uint8_t> *request_der) {
1003
0
  request_der->clear();
1004
1005
0
  bssl::ScopedCBB cbb;
1006
1007
  // This initial buffer size is big enough for 20 octet long serial numbers
1008
  // (upper bound from RFC 5280) and then a handful of extra bytes. This
1009
  // number doesn't matter for correctness.
1010
0
  const size_t kInitialBufferSize = 100;
1011
1012
0
  if (!CBB_init(cbb.get(), kInitialBufferSize)) {
1013
0
    return false;
1014
0
  }
1015
1016
  //   OCSPRequest     ::=     SEQUENCE {
1017
  //       tbsRequest                  TBSRequest,
1018
  //       optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
1019
  //
1020
  //   TBSRequest      ::=     SEQUENCE {
1021
  //       version             [0]     EXPLICIT Version DEFAULT v1,
1022
  //       requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
1023
  //       requestList                 SEQUENCE OF Request,
1024
  //       requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
1025
0
  CBB ocsp_request;
1026
0
  if (!CBB_add_asn1(cbb.get(), &ocsp_request, CBS_ASN1_SEQUENCE)) {
1027
0
    return false;
1028
0
  }
1029
1030
0
  CBB tbs_request;
1031
0
  if (!CBB_add_asn1(&ocsp_request, &tbs_request, CBS_ASN1_SEQUENCE)) {
1032
0
    return false;
1033
0
  }
1034
1035
  // "version", "requestorName", and "requestExtensions" are omitted.
1036
1037
0
  CBB request_list;
1038
0
  if (!CBB_add_asn1(&tbs_request, &request_list, CBS_ASN1_SEQUENCE)) {
1039
0
    return false;
1040
0
  }
1041
1042
0
  CBB request;
1043
0
  if (!CBB_add_asn1(&request_list, &request, CBS_ASN1_SEQUENCE)) {
1044
0
    return false;
1045
0
  }
1046
1047
  //   Request         ::=     SEQUENCE {
1048
  //       reqCert                     CertID,
1049
  //       singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
1050
0
  CBB req_cert;
1051
0
  if (!CBB_add_asn1(&request, &req_cert, CBS_ASN1_SEQUENCE)) {
1052
0
    return false;
1053
0
  }
1054
1055
  //   CertID          ::=     SEQUENCE {
1056
  //       hashAlgorithm       AlgorithmIdentifier,
1057
  //       issuerNameHash      OCTET STRING, -- Hash of issuer's DN
1058
  //       issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
1059
  //       serialNumber        CertificateSerialNumber }
1060
  //
1061
  // It is unclear whether the parameters for hashAlgorithm should be omitted or
1062
  // NULL. Section 2.1 of RFC 4055 would suggest omitting it is the right
1063
  // default behavior. However, both OpenSSL and Go include it, so we match them
1064
  // for now.
1065
1066
  // TODO(eroman): Don't use SHA1.
1067
0
  const EVP_MD *md = EVP_sha1();
1068
0
  if (!EVP_marshal_digest_algorithm(&req_cert, md)) {
1069
0
    return false;
1070
0
  }
1071
1072
0
  AppendHashAsOctetString(md, &req_cert, issuer->tbs().subject_tlv);
1073
1074
0
  der::Input key_tlv;
1075
0
  if (!GetSubjectPublicKeyBytes(issuer->tbs().spki_tlv, &key_tlv)) {
1076
0
    return false;
1077
0
  }
1078
0
  AppendHashAsOctetString(md, &req_cert, key_tlv);
1079
1080
0
  CBB serial_number;
1081
0
  if (!CBB_add_asn1(&req_cert, &serial_number, CBS_ASN1_INTEGER)) {
1082
0
    return false;
1083
0
  }
1084
0
  if (!CBB_add_bytes(&serial_number, cert->tbs().serial_number.data(),
1085
0
                     cert->tbs().serial_number.size())) {
1086
0
    return false;
1087
0
  }
1088
1089
0
  uint8_t *result_bytes;
1090
0
  size_t result_bytes_length;
1091
0
  if (!CBB_finish(cbb.get(), &result_bytes, &result_bytes_length)) {
1092
0
    return false;
1093
0
  }
1094
0
  bssl::UniquePtr<uint8_t> delete_tbs_cert_bytes(result_bytes);
1095
1096
0
  request_der->assign(result_bytes, result_bytes + result_bytes_length);
1097
0
  return true;
1098
0
}
1099
1100
// From RFC 2560 section A.1.1:
1101
//
1102
//    An OCSP request using the GET method is constructed as follows:
1103
//
1104
//    GET {url}/{url-encoding of base-64 encoding of the DER encoding of
1105
//    the OCSPRequest}
1106
std::optional<std::string> CreateOCSPGetURL(
1107
    const ParsedCertificate *cert, const ParsedCertificate *issuer,
1108
0
    std::string_view ocsp_responder_url) {
1109
0
  std::vector<uint8_t> ocsp_request_der;
1110
0
  if (!CreateOCSPRequest(cert, issuer, &ocsp_request_der)) {
1111
    // Unexpected (means BoringSSL failed an operation).
1112
0
    return std::nullopt;
1113
0
  }
1114
1115
  // Base64 encode the request data.
1116
0
  size_t len;
1117
0
  if (!EVP_EncodedLength(&len, ocsp_request_der.size())) {
1118
0
    return std::nullopt;
1119
0
  }
1120
0
  std::vector<uint8_t> encoded(len);
1121
0
  len = EVP_EncodeBlock(encoded.data(), ocsp_request_der.data(),
1122
0
                        ocsp_request_der.size());
1123
1124
0
  std::string b64_encoded(encoded.begin(), encoded.begin() + len);
1125
1126
  // In theory +, /, and = are valid in paths and don't need to be escaped.
1127
  // However from the example in RFC 5019 section 5 it is clear that the intent
1128
  // is to escape non-alphanumeric characters (the example conclusively escapes
1129
  // '/' and '=', but doesn't clarify '+').
1130
0
  b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "+", "%2B");
1131
0
  b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "/", "%2F");
1132
0
  b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "=", "%3D");
1133
1134
  // No attempt is made to collapse double slashes for URLs that end in slash,
1135
  // since the spec doesn't do that.
1136
0
  return std::string(ocsp_responder_url) + "/" + b64_encoded;
1137
0
}
1138
1139
BSSL_NAMESPACE_END