1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/test/revocation_builder.h"
6 
7 #include "base/hash/sha1.h"
8 #include "base/strings/string_util.h"
9 #include "net/cert/asn1_util.h"
10 #include "net/cert/x509_util.h"
11 #include "net/der/encode_values.h"
12 #include "net/der/input.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/boringssl/src/include/openssl/bytestring.h"
15 #include "third_party/boringssl/src/include/openssl/mem.h"
16 
17 namespace net {
18 
19 namespace {
20 
Sha256WithRSAEncryption()21 std::string Sha256WithRSAEncryption() {
22   const uint8_t kSha256WithRSAEncryption[] = {0x30, 0x0D, 0x06, 0x09, 0x2a,
23                                               0x86, 0x48, 0x86, 0xf7, 0x0d,
24                                               0x01, 0x01, 0x0b, 0x05, 0x00};
25   return std::string(std::begin(kSha256WithRSAEncryption),
26                      std::end(kSha256WithRSAEncryption));
27 }
28 
Sha1WithRSAEncryption()29 std::string Sha1WithRSAEncryption() {
30   const uint8_t kSha1WithRSAEncryption[] = {0x30, 0x0D, 0x06, 0x09, 0x2a,
31                                             0x86, 0x48, 0x86, 0xf7, 0x0d,
32                                             0x01, 0x01, 0x05, 0x05, 0x00};
33   return std::string(std::begin(kSha1WithRSAEncryption),
34                      std::end(kSha1WithRSAEncryption));
35 }
36 
Md5WithRSAEncryption()37 std::string Md5WithRSAEncryption() {
38   const uint8_t kMd5WithRSAEncryption[] = {0x30, 0x0d, 0x06, 0x09, 0x2a,
39                                            0x86, 0x48, 0x86, 0xf7, 0x0d,
40                                            0x01, 0x01, 0x04, 0x05, 0x00};
41   return std::string(std::begin(kMd5WithRSAEncryption),
42                      std::end(kMd5WithRSAEncryption));
43 }
44 
Sha1()45 std::string Sha1() {
46   // SEQUENCE { OBJECT_IDENTIFIER { 1.3.14.3.2.26 } }
47   const uint8_t kSHA1[] = {0x30, 0x07, 0x06, 0x05, 0x2b,
48                            0x0e, 0x03, 0x02, 0x1a};
49   return std::string(std::begin(kSHA1), std::end(kSHA1));
50 }
51 
52 // Adds bytes (specified as a StringPiece) to the given CBB.
53 // The argument ordering follows the boringssl CBB_* api style.
CBBAddBytes(CBB * cbb,base::StringPiece bytes)54 bool CBBAddBytes(CBB* cbb, base::StringPiece bytes) {
55   return CBB_add_bytes(cbb, reinterpret_cast<const uint8_t*>(bytes.data()),
56                        bytes.size());
57 }
58 
59 // Adds bytes (from fixed size array) to the given CBB.
60 // The argument ordering follows the boringssl CBB_* api style.
61 template <size_t N>
CBBAddBytes(CBB * cbb,const uint8_t (& data)[N])62 bool CBBAddBytes(CBB* cbb, const uint8_t (&data)[N]) {
63   return CBB_add_bytes(cbb, data, N);
64 }
65 
66 // Adds a GeneralizedTime value to the given CBB.
67 // The argument ordering follows the boringssl CBB_* api style.
CBBAddGeneralizedTime(CBB * cbb,const base::Time & time)68 bool CBBAddGeneralizedTime(CBB* cbb, const base::Time& time) {
69   der::GeneralizedTime generalized_time;
70   if (!der::EncodeTimeAsGeneralizedTime(time, &generalized_time))
71     return false;
72   CBB time_cbb;
73   uint8_t out[der::kGeneralizedTimeLength];
74   if (!der::EncodeGeneralizedTime(generalized_time, out) ||
75       !CBB_add_asn1(cbb, &time_cbb, CBS_ASN1_GENERALIZEDTIME) ||
76       !CBBAddBytes(&time_cbb, out) || !CBB_flush(cbb))
77     return false;
78   return true;
79 }
80 
81 // Finalizes the CBB to a std::string.
FinishCBB(CBB * cbb)82 std::string FinishCBB(CBB* cbb) {
83   size_t cbb_len;
84   uint8_t* cbb_bytes;
85 
86   if (!CBB_finish(cbb, &cbb_bytes, &cbb_len)) {
87     ADD_FAILURE() << "CBB_finish() failed";
88     return std::string();
89   }
90 
91   bssl::UniquePtr<uint8_t> delete_bytes(cbb_bytes);
92   return std::string(reinterpret_cast<char*>(cbb_bytes), cbb_len);
93 }
94 
PKeyToSPK(const EVP_PKEY * pkey)95 std::string PKeyToSPK(const EVP_PKEY* pkey) {
96   bssl::ScopedCBB cbb;
97   if (!CBB_init(cbb.get(), 64) || !EVP_marshal_public_key(cbb.get(), pkey)) {
98     ADD_FAILURE();
99     return std::string();
100   }
101   std::string spki = FinishCBB(cbb.get());
102 
103   base::StringPiece spk;
104   if (!asn1::ExtractSubjectPublicKeyFromSPKI(spki, &spk)) {
105     ADD_FAILURE();
106     return std::string();
107   }
108 
109   // ExtractSubjectPublicKeyFromSPKI() includes the unused bit count. For this
110   // application, the unused bit count must be zero, and is not included in the
111   // result.
112   if (!base::StartsWith(spk, "\0")) {
113     ADD_FAILURE();
114     return std::string();
115   }
116   spk.remove_prefix(1);
117 
118   return spk.as_string();
119 }
120 
121 // Returns a DER-encoded OCSPResponse with the given |response_status|.
122 // |response_type| and |response| are optional and may be empty.
EncodeOCSPResponse(OCSPResponse::ResponseStatus response_status,der::Input response_type,std::string response)123 std::string EncodeOCSPResponse(OCSPResponse::ResponseStatus response_status,
124                                der::Input response_type,
125                                std::string response) {
126   // RFC 6960 section 4.2.1:
127   //
128   //    OCSPResponse ::= SEQUENCE {
129   //       responseStatus         OCSPResponseStatus,
130   //       responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
131   //
132   //    OCSPResponseStatus ::= ENUMERATED {
133   //        successful            (0),  -- Response has valid confirmations
134   //        malformedRequest      (1),  -- Illegal confirmation request
135   //        internalError         (2),  -- Internal error in issuer
136   //        tryLater              (3),  -- Try again later
137   //                                    -- (4) is not used
138   //        sigRequired           (5),  -- Must sign the request
139   //        unauthorized          (6)   -- Request unauthorized
140   //    }
141   //
142   //    The value for responseBytes consists of an OBJECT IDENTIFIER and a
143   //    response syntax identified by that OID encoded as an OCTET STRING.
144   //
145   //    ResponseBytes ::=       SEQUENCE {
146   //        responseType   OBJECT IDENTIFIER,
147   //        response       OCTET STRING }
148   bssl::ScopedCBB cbb;
149   CBB ocsp_response, ocsp_response_status, ocsp_response_bytes,
150       ocsp_response_bytes_sequence, ocsp_response_type,
151       ocsp_response_octet_string;
152 
153   if (!CBB_init(cbb.get(), 64 + response_type.Length() + response.size()) ||
154       !CBB_add_asn1(cbb.get(), &ocsp_response, CBS_ASN1_SEQUENCE) ||
155       !CBB_add_asn1(&ocsp_response, &ocsp_response_status,
156                     CBS_ASN1_ENUMERATED) ||
157       !CBB_add_u8(&ocsp_response_status,
158                   static_cast<uint8_t>(response_status))) {
159     ADD_FAILURE();
160     return std::string();
161   }
162 
163   if (response_type.Length()) {
164     if (!CBB_add_asn1(&ocsp_response, &ocsp_response_bytes,
165                       CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
166         !CBB_add_asn1(&ocsp_response_bytes, &ocsp_response_bytes_sequence,
167                       CBS_ASN1_SEQUENCE) ||
168         !CBB_add_asn1(&ocsp_response_bytes_sequence, &ocsp_response_type,
169                       CBS_ASN1_OBJECT) ||
170         !CBBAddBytes(&ocsp_response_type, response_type.AsStringPiece()) ||
171         !CBB_add_asn1(&ocsp_response_bytes_sequence,
172                       &ocsp_response_octet_string, CBS_ASN1_OCTETSTRING) ||
173         !CBBAddBytes(&ocsp_response_octet_string, response)) {
174       ADD_FAILURE();
175       return std::string();
176     }
177   }
178 
179   return FinishCBB(cbb.get());
180 }
181 
182 // Adds a DER-encoded OCSP SingleResponse to |responses_cbb|.
183 // |issuer_name_hash| and |issuer_key_hash| should be binary SHA1 hashes.
AddOCSPSingleResponse(CBB * responses_cbb,const OCSPBuilderSingleResponse & response,const std::string & issuer_name_hash,const std::string & issuer_key_hash)184 bool AddOCSPSingleResponse(CBB* responses_cbb,
185                            const OCSPBuilderSingleResponse& response,
186                            const std::string& issuer_name_hash,
187                            const std::string& issuer_key_hash) {
188   // RFC 6960 section 4.2.1:
189   //
190   //    SingleResponse ::= SEQUENCE {
191   //       certID                       CertID,
192   //       certStatus                   CertStatus,
193   //       thisUpdate                   GeneralizedTime,
194   //       nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
195   //       singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }
196   //
197   //    CertStatus ::= CHOICE {
198   //        good        [0]     IMPLICIT NULL,
199   //        revoked     [1]     IMPLICIT RevokedInfo,
200   //        unknown     [2]     IMPLICIT UnknownInfo }
201   //
202   //    RevokedInfo ::= SEQUENCE {
203   //        revocationTime              GeneralizedTime,
204   //        revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
205   //
206   //    UnknownInfo ::= NULL
207   //
208   // RFC 6960 section 4.1.1:
209   //   CertID          ::=     SEQUENCE {
210   //        hashAlgorithm       AlgorithmIdentifier,
211   //        issuerNameHash      OCTET STRING, -- Hash of issuer's DN
212   //        issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
213   //        serialNumber        CertificateSerialNumber }
214   //
215   //  The contents of CertID include the following fields:
216   //
217   //    o  hashAlgorithm is the hash algorithm used to generate the
218   //       issuerNameHash and issuerKeyHash values.
219   //
220   //    o  issuerNameHash is the hash of the issuer's distinguished name
221   //       (DN).  The hash shall be calculated over the DER encoding of the
222   //       issuer's name field in the certificate being checked.
223   //
224   //    o  issuerKeyHash is the hash of the issuer's public key.  The hash
225   //       shall be calculated over the value (excluding tag and length) of
226   //       the subject public key field in the issuer's certificate.
227   //
228   //    o  serialNumber is the serial number of the certificate for which
229   //       status is being requested.
230 
231   CBB single_response, issuer_name_hash_cbb, issuer_key_hash_cbb, cert_id;
232   if (!CBB_add_asn1(responses_cbb, &single_response, CBS_ASN1_SEQUENCE) ||
233       !CBB_add_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE) ||
234       !CBBAddBytes(&cert_id, Sha1()) ||
235       !CBB_add_asn1(&cert_id, &issuer_name_hash_cbb, CBS_ASN1_OCTETSTRING) ||
236       !CBBAddBytes(&issuer_name_hash_cbb, issuer_name_hash) ||
237       !CBB_add_asn1(&cert_id, &issuer_key_hash_cbb, CBS_ASN1_OCTETSTRING) ||
238       !CBBAddBytes(&issuer_key_hash_cbb, issuer_key_hash) ||
239       !CBB_add_asn1_uint64(&cert_id, response.serial)) {
240     ADD_FAILURE();
241     return false;
242   }
243 
244   unsigned int cert_status_tag_number;
245   switch (response.cert_status) {
246     case OCSPRevocationStatus::GOOD:
247       cert_status_tag_number = CBS_ASN1_CONTEXT_SPECIFIC | 0;
248       break;
249     case OCSPRevocationStatus::REVOKED:
250       cert_status_tag_number =
251           CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1;
252       break;
253     case OCSPRevocationStatus::UNKNOWN:
254       cert_status_tag_number = CBS_ASN1_CONTEXT_SPECIFIC | 2;
255       break;
256   }
257 
258   CBB cert_status_cbb;
259   if (!CBB_add_asn1(&single_response, &cert_status_cbb,
260                     cert_status_tag_number)) {
261     ADD_FAILURE();
262     return false;
263   }
264   if (response.cert_status == OCSPRevocationStatus::REVOKED &&
265       !CBBAddGeneralizedTime(&cert_status_cbb, response.revocation_time)) {
266     ADD_FAILURE();
267     return false;
268   }
269 
270   CBB next_update_cbb;
271   if (!CBBAddGeneralizedTime(&single_response, response.this_update) ||
272       !CBB_add_asn1(&single_response, &next_update_cbb,
273                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
274       !CBBAddGeneralizedTime(&next_update_cbb, response.next_update)) {
275     ADD_FAILURE();
276     return false;
277   }
278 
279   return CBB_flush(responses_cbb);
280 }
281 
282 }  // namespace
283 
BuildOCSPResponseError(OCSPResponse::ResponseStatus response_status)284 std::string BuildOCSPResponseError(
285     OCSPResponse::ResponseStatus response_status) {
286   DCHECK_NE(response_status, OCSPResponse::ResponseStatus::SUCCESSFUL);
287   return EncodeOCSPResponse(response_status, der::Input(), std::string());
288 }
289 
BuildOCSPResponse(const std::string & responder_subject,EVP_PKEY * responder_key,base::Time produced_at,const std::vector<OCSPBuilderSingleResponse> & responses)290 std::string BuildOCSPResponse(
291     const std::string& responder_subject,
292     EVP_PKEY* responder_key,
293     base::Time produced_at,
294     const std::vector<OCSPBuilderSingleResponse>& responses) {
295   std::string responder_name_hash = base::SHA1HashString(responder_subject);
296   std::string responder_key_hash =
297       base::SHA1HashString(PKeyToSPK(responder_key));
298 
299   // RFC 6960 section 4.2.1:
300   //
301   //    ResponseData ::= SEQUENCE {
302   //       version              [0] EXPLICIT Version DEFAULT v1,
303   //       responderID              ResponderID,
304   //       producedAt               GeneralizedTime,
305   //       responses                SEQUENCE OF SingleResponse,
306   //       responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
307   //
308   //    ResponderID ::= CHOICE {
309   //       byName               [1] Name,
310   //       byKey                [2] KeyHash }
311   //
312   //    KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
313   //    (excluding the tag and length fields)
314   bssl::ScopedCBB tbs_cbb;
315   CBB response_data, responder_id, responder_id_by_key, responses_cbb;
316   if (!CBB_init(tbs_cbb.get(), 64) ||
317       !CBB_add_asn1(tbs_cbb.get(), &response_data, CBS_ASN1_SEQUENCE) ||
318       // Version is the default v1, so it is not encoded.
319       !CBB_add_asn1(&response_data, &responder_id,
320                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 2) ||
321       !CBB_add_asn1(&responder_id, &responder_id_by_key,
322                     CBS_ASN1_OCTETSTRING) ||
323       !CBBAddBytes(&responder_id_by_key, responder_key_hash) ||
324       !CBBAddGeneralizedTime(&response_data, produced_at) ||
325       !CBB_add_asn1(&response_data, &responses_cbb, CBS_ASN1_SEQUENCE)) {
326     ADD_FAILURE();
327     return std::string();
328   }
329 
330   for (const auto& response : responses) {
331     if (!AddOCSPSingleResponse(&responses_cbb, response, responder_name_hash,
332                                responder_key_hash)) {
333       return std::string();
334     }
335   }
336 
337   // responseExtensions not currently supported.
338 
339   return BuildOCSPResponseWithResponseData(responder_key,
340                                            FinishCBB(tbs_cbb.get()));
341 }
342 
BuildOCSPResponseWithResponseData(EVP_PKEY * responder_key,const std::string & tbs_response_data)343 std::string BuildOCSPResponseWithResponseData(
344     EVP_PKEY* responder_key,
345     const std::string& tbs_response_data) {
346   //    For a basic OCSP responder, responseType will be id-pkix-ocsp-basic.
347   //
348   //    id-pkix-ocsp           OBJECT IDENTIFIER ::= { id-ad-ocsp }
349   //    id-pkix-ocsp-basic     OBJECT IDENTIFIER ::= { id-pkix-ocsp 1 }
350   //
351   //    The value for response SHALL be the DER encoding of
352   //    BasicOCSPResponse.
353   //
354   //    BasicOCSPResponse       ::= SEQUENCE {
355   //       tbsResponseData      ResponseData,
356   //       signatureAlgorithm   AlgorithmIdentifier,
357   //       signature            BIT STRING,
358   //       certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
359   //
360   //    The value for signature SHALL be computed on the hash of the DER
361   //    encoding of ResponseData.  The responder MAY include certificates in
362   //    the certs field of BasicOCSPResponse that help the OCSP client verify
363   //    the responder's signature.  If no certificates are included, then
364   //    certs SHOULD be absent.
365   //
366   bssl::ScopedCBB basic_ocsp_response_cbb;
367   CBB basic_ocsp_response, signature;
368   bssl::ScopedEVP_MD_CTX ctx;
369   uint8_t* sig_out;
370   size_t sig_len;
371   if (!CBB_init(basic_ocsp_response_cbb.get(), 64 + tbs_response_data.size()) ||
372       !CBB_add_asn1(basic_ocsp_response_cbb.get(), &basic_ocsp_response,
373                     CBS_ASN1_SEQUENCE) ||
374       !CBBAddBytes(&basic_ocsp_response, tbs_response_data) ||
375       !CBBAddBytes(&basic_ocsp_response, Sha256WithRSAEncryption()) ||
376       !CBB_add_asn1(&basic_ocsp_response, &signature, CBS_ASN1_BITSTRING) ||
377       !CBB_add_u8(&signature, 0 /* no unused bits */) ||
378       !EVP_DigestSignInit(ctx.get(), nullptr, EVP_sha256(), nullptr,
379                           responder_key) ||
380       !EVP_DigestSign(
381           ctx.get(), nullptr, &sig_len,
382           reinterpret_cast<const uint8_t*>(tbs_response_data.data()),
383           tbs_response_data.size()) ||
384       !CBB_reserve(&signature, &sig_out, sig_len) ||
385       !EVP_DigestSign(
386           ctx.get(), sig_out, &sig_len,
387           reinterpret_cast<const uint8_t*>(tbs_response_data.data()),
388           tbs_response_data.size()) ||
389       !CBB_did_write(&signature, sig_len)) {
390     ADD_FAILURE();
391     return std::string();
392   }
393 
394   // certs field not currently supported.
395 
396   return EncodeOCSPResponse(OCSPResponse::ResponseStatus::SUCCESSFUL,
397                             BasicOCSPResponseOid(),
398                             FinishCBB(basic_ocsp_response_cbb.get()));
399 }
400 
BuildCrl(const std::string & crl_issuer_subject,EVP_PKEY * crl_issuer_key,const std::vector<uint64_t> & revoked_serials,DigestAlgorithm digest)401 std::string BuildCrl(const std::string& crl_issuer_subject,
402                      EVP_PKEY* crl_issuer_key,
403                      const std::vector<uint64_t>& revoked_serials,
404                      DigestAlgorithm digest) {
405   std::string signature_algorithm;
406   const EVP_MD* md = nullptr;
407   switch (digest) {
408     case DigestAlgorithm::Sha256: {
409       signature_algorithm = Sha256WithRSAEncryption();
410       md = EVP_sha256();
411       break;
412     }
413 
414     case DigestAlgorithm::Sha1: {
415       signature_algorithm = Sha1WithRSAEncryption();
416       md = EVP_sha1();
417       break;
418     }
419 
420     case DigestAlgorithm::Md5: {
421       signature_algorithm = Md5WithRSAEncryption();
422       md = EVP_md5();
423       break;
424     }
425 
426     default:
427       ADD_FAILURE();
428       return std::string();
429   }
430   //    TBSCertList  ::=  SEQUENCE  {
431   //         version                 Version OPTIONAL,
432   //                                      -- if present, MUST be v2
433   //         signature               AlgorithmIdentifier,
434   //         issuer                  Name,
435   //         thisUpdate              Time,
436   //         nextUpdate              Time OPTIONAL,
437   //         revokedCertificates     SEQUENCE OF SEQUENCE  {
438   //              userCertificate         CertificateSerialNumber,
439   //              revocationDate          Time,
440   //              crlEntryExtensions      Extensions OPTIONAL
441   //                                       -- if present, version MUST be v2
442   //                                   }  OPTIONAL,
443   //         crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
444   //                                       -- if present, version MUST be v2
445   //                                   }
446   bssl::ScopedCBB tbs_cbb;
447   CBB tbs_cert_list, revoked_serials_cbb;
448   if (!CBB_init(tbs_cbb.get(), 10) ||
449       !CBB_add_asn1(tbs_cbb.get(), &tbs_cert_list, CBS_ASN1_SEQUENCE) ||
450       !CBB_add_asn1_uint64(&tbs_cert_list, 1 /* V2 */) ||
451       !CBBAddBytes(&tbs_cert_list, signature_algorithm) ||
452       !CBBAddBytes(&tbs_cert_list, crl_issuer_subject) ||
453       !x509_util::CBBAddTime(
454           &tbs_cert_list, base::Time::Now() - base::TimeDelta::FromDays(1)) ||
455       !x509_util::CBBAddTime(
456           &tbs_cert_list, base::Time::Now() + base::TimeDelta::FromDays(6))) {
457     ADD_FAILURE();
458     return std::string();
459   }
460   if (!revoked_serials.empty()) {
461     if (!CBB_add_asn1(&tbs_cert_list, &revoked_serials_cbb,
462                       CBS_ASN1_SEQUENCE)) {
463       ADD_FAILURE();
464       return std::string();
465     }
466     for (const int64_t revoked_serial : revoked_serials) {
467       CBB revoked_serial_cbb;
468       if (!CBB_add_asn1(&revoked_serials_cbb, &revoked_serial_cbb,
469                         CBS_ASN1_SEQUENCE) ||
470           !CBB_add_asn1_uint64(&revoked_serial_cbb, revoked_serial) ||
471           !x509_util::CBBAddTime(
472               &revoked_serial_cbb,
473               base::Time::Now() - base::TimeDelta::FromDays(1)) ||
474           !CBB_flush(&revoked_serials_cbb)) {
475         ADD_FAILURE();
476         return std::string();
477       }
478     }
479   }
480 
481   std::string tbs_tlv = FinishCBB(tbs_cbb.get());
482 
483   //    CertificateList  ::=  SEQUENCE  {
484   //         tbsCertList          TBSCertList,
485   //         signatureAlgorithm   AlgorithmIdentifier,
486   //         signatureValue       BIT STRING  }
487   bssl::ScopedCBB crl_cbb;
488   CBB cert_list, signature;
489   bssl::ScopedEVP_MD_CTX ctx;
490   uint8_t* sig_out;
491   size_t sig_len;
492   if (!CBB_init(crl_cbb.get(), 10) ||
493       !CBB_add_asn1(crl_cbb.get(), &cert_list, CBS_ASN1_SEQUENCE) ||
494       !CBBAddBytes(&cert_list, tbs_tlv) ||
495       !CBBAddBytes(&cert_list, signature_algorithm) ||
496       !CBB_add_asn1(&cert_list, &signature, CBS_ASN1_BITSTRING) ||
497       !CBB_add_u8(&signature, 0 /* no unused bits */) ||
498       !EVP_DigestSignInit(ctx.get(), nullptr, md, nullptr, crl_issuer_key) ||
499       !EVP_DigestSign(ctx.get(), nullptr, &sig_len,
500                       reinterpret_cast<const uint8_t*>(tbs_tlv.data()),
501                       tbs_tlv.size()) ||
502       !CBB_reserve(&signature, &sig_out, sig_len) ||
503       !EVP_DigestSign(ctx.get(), sig_out, &sig_len,
504                       reinterpret_cast<const uint8_t*>(tbs_tlv.data()),
505                       tbs_tlv.size()) ||
506       !CBB_did_write(&signature, sig_len)) {
507     ADD_FAILURE();
508     return std::string();
509   }
510   return FinishCBB(crl_cbb.get());
511 }
512 }  // namespace net
513