blob: 4aed2248b6ab96e092cbb08b7ed39fd0f23bcfff [file] [log] [blame]
Janis Danisevskisa7c72db2020-11-05 12:02:22 -08001/*
2 * Copyright 2020, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <certificate_utils.h>
18
19#include <openssl/err.h>
20#include <openssl/evp.h>
21#include <openssl/mem.h>
22#include <openssl/x509v3.h>
23
24#include <functional>
25#include <limits>
26#include <string>
27#include <variant>
28#include <vector>
29
30namespace keystore {
31
32namespace {
33
34constexpr int kDigitalSignatureKeyUsageBit = 0;
35constexpr int kKeyEnciphermentKeyUsageBit = 2;
36constexpr int kDataEnciphermentKeyUsageBit = 3;
37constexpr int kKeyCertSignBit = 5;
38constexpr int kMaxKeyUsageBit = 8;
39
40DEFINE_OPENSSL_OBJECT_POINTER(ASN1_STRING);
41DEFINE_OPENSSL_OBJECT_POINTER(RSA_PSS_PARAMS);
42DEFINE_OPENSSL_OBJECT_POINTER(AUTHORITY_KEYID);
43DEFINE_OPENSSL_OBJECT_POINTER(BASIC_CONSTRAINTS);
44DEFINE_OPENSSL_OBJECT_POINTER(X509_ALGOR);
Janis Danisevskis2c084012021-01-31 22:23:17 -080045DEFINE_OPENSSL_OBJECT_POINTER(BIGNUM);
Janis Danisevskisa7c72db2020-11-05 12:02:22 -080046
47} // namespace
48
Janis Danisevskis2c084012021-01-31 22:23:17 -080049constexpr const char kDefaultCommonName[] = "Default Common Name";
50
51std::variant<CertUtilsError, X509_NAME_Ptr>
52makeCommonName(std::optional<std::reference_wrapper<const std::vector<uint8_t>>> name) {
53 if (name) {
54 const uint8_t* p = name->get().data();
55 X509_NAME_Ptr x509_name(d2i_X509_NAME(nullptr, &p, name->get().size()));
56 if (!x509_name) {
57 return CertUtilsError::MemoryAllocation;
58 }
59 return x509_name;
60 }
61
Janis Danisevskisa7c72db2020-11-05 12:02:22 -080062 X509_NAME_Ptr x509_name(X509_NAME_new());
63 if (!x509_name) {
Janis Danisevskis2c084012021-01-31 22:23:17 -080064 return CertUtilsError::MemoryAllocation;
Janis Danisevskisa7c72db2020-11-05 12:02:22 -080065 }
66 if (!X509_NAME_add_entry_by_txt(x509_name.get(), "CN", MBSTRING_ASC,
Janis Danisevskis2c084012021-01-31 22:23:17 -080067 reinterpret_cast<const uint8_t*>(kDefaultCommonName),
68 sizeof(kDefaultCommonName) - 1, -1 /* loc */, 0 /* set */)) {
Janis Danisevskisa7c72db2020-11-05 12:02:22 -080069 return CertUtilsError::BoringSsl;
70 }
71 return x509_name;
72}
73
74std::variant<CertUtilsError, std::vector<uint8_t>> makeKeyId(const X509* cert) {
75 std::vector<uint8_t> keyid(20);
76 unsigned int len;
77 if (!X509_pubkey_digest(cert, EVP_sha1(), keyid.data(), &len)) {
78 return CertUtilsError::Encoding;
79 }
80 return keyid;
81}
82
83std::variant<CertUtilsError, AUTHORITY_KEYID_Ptr>
84makeAuthorityKeyExtension(const std::vector<uint8_t>& keyid) {
85 AUTHORITY_KEYID_Ptr auth_key(AUTHORITY_KEYID_new());
86 if (!auth_key) {
87 return CertUtilsError::MemoryAllocation;
88 }
89
90 auth_key->keyid = ASN1_OCTET_STRING_new();
91 if (auth_key->keyid == nullptr) {
92 return CertUtilsError::MemoryAllocation;
93 }
94
95 if (!ASN1_OCTET_STRING_set(auth_key->keyid, keyid.data(), keyid.size())) {
96 return CertUtilsError::BoringSsl;
97 }
98
99 return auth_key;
100}
101
102std::variant<CertUtilsError, ASN1_OCTET_STRING_Ptr>
103makeSubjectKeyExtension(const std::vector<uint8_t>& keyid) {
104
105 // Build OCTET_STRING
106 ASN1_OCTET_STRING_Ptr keyid_str(ASN1_OCTET_STRING_new());
107 if (!keyid_str || !ASN1_OCTET_STRING_set(keyid_str.get(), keyid.data(), keyid.size())) {
108 return CertUtilsError::BoringSsl;
109 }
110
111 return keyid_str;
112}
113
114std::variant<CertUtilsError, BASIC_CONSTRAINTS_Ptr>
115makeBasicConstraintsExtension(bool is_ca, std::optional<int> path_length) {
116
117 BASIC_CONSTRAINTS_Ptr bcons(BASIC_CONSTRAINTS_new());
118 if (!bcons) {
119 return CertUtilsError::MemoryAllocation;
120 }
121
122 bcons->ca = is_ca;
123 bcons->pathlen = nullptr;
124 if (path_length) {
125 bcons->pathlen = ASN1_INTEGER_new();
126 if (bcons->pathlen == nullptr || !ASN1_INTEGER_set(bcons->pathlen, *path_length)) {
127 return CertUtilsError::BoringSsl;
128 }
129 }
130
131 return bcons;
132}
133
134std::variant<CertUtilsError, ASN1_BIT_STRING_Ptr>
135makeKeyUsageExtension(bool is_signing_key, bool is_encryption_key, bool is_cert_key) {
136 // Build BIT_STRING with correct contents.
137 ASN1_BIT_STRING_Ptr key_usage(ASN1_BIT_STRING_new());
138 if (!key_usage) {
139 return CertUtilsError::BoringSsl;
140 }
141
142 for (size_t i = 0; i <= kMaxKeyUsageBit; ++i) {
143 if (!ASN1_BIT_STRING_set_bit(key_usage.get(), i, 0)) {
144 return CertUtilsError::BoringSsl;
145 }
146 }
147
148 if (is_signing_key) {
149 if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kDigitalSignatureKeyUsageBit, 1)) {
150 return CertUtilsError::BoringSsl;
151 }
152 }
153
154 if (is_encryption_key) {
155 if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyEnciphermentKeyUsageBit, 1) ||
156 !ASN1_BIT_STRING_set_bit(key_usage.get(), kDataEnciphermentKeyUsageBit, 1)) {
157 return CertUtilsError::BoringSsl;
158 }
159 }
160
161 if (is_cert_key) {
162 if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyCertSignBit, 1)) {
163 return CertUtilsError::BoringSsl;
164 }
165 }
166
167 return key_usage;
168}
169
170// Creates a rump certificate structure with serial, subject and issuer names, as well as
171// activation and expiry date.
172// Callers should pass an empty X509_Ptr and check the return value for CertUtilsError::Ok (0)
173// before accessing the result.
174std::variant<CertUtilsError, X509_Ptr>
Janis Danisevskis2c084012021-01-31 22:23:17 -0800175makeCertRump(std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,
176 std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,
177 const uint64_t activeDateTimeMilliSeconds,
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800178 const uint64_t usageExpireDateTimeMilliSeconds) {
179
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800180 // Create certificate structure.
181 X509_Ptr certificate(X509_new());
182 if (!certificate) {
183 return CertUtilsError::BoringSsl;
184 }
185
186 // Set the X509 version.
187 if (!X509_set_version(certificate.get(), 2 /* version 3, but zero-based */)) {
188 return CertUtilsError::BoringSsl;
189 }
190
Janis Danisevskis2c084012021-01-31 22:23:17 -0800191 BIGNUM_Ptr bn_serial;
192 if (serial) {
193 bn_serial = BIGNUM_Ptr(BN_bin2bn(serial->get().data(), serial->get().size(), nullptr));
194 if (!bn_serial) {
195 return CertUtilsError::MemoryAllocation;
196 }
197 } else {
198 bn_serial = BIGNUM_Ptr(BN_new());
199 if (!bn_serial) {
200 return CertUtilsError::MemoryAllocation;
201 }
202 BN_zero(bn_serial.get());
203 }
204
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800205 // Set the certificate serialNumber
206 ASN1_INTEGER_Ptr serialNumber(ASN1_INTEGER_new());
Janis Danisevskis2c084012021-01-31 22:23:17 -0800207 if (!serialNumber || !BN_to_ASN1_INTEGER(bn_serial.get(), serialNumber.get()) ||
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800208 !X509_set_serialNumber(certificate.get(), serialNumber.get() /* Don't release; copied */))
209 return CertUtilsError::BoringSsl;
210
211 // Set Subject Name
212 auto subjectName = makeCommonName(subject);
213 if (auto x509_subject = std::get_if<X509_NAME_Ptr>(&subjectName)) {
214 if (!X509_set_subject_name(certificate.get(), x509_subject->get() /* copied */)) {
215 return CertUtilsError::BoringSsl;
216 }
217 } else {
218 return std::get<CertUtilsError>(subjectName);
219 }
220
221 // Set activation date.
222 ASN1_TIME_Ptr notBefore(ASN1_TIME_new());
223 if (!notBefore || !ASN1_TIME_set(notBefore.get(), activeDateTimeMilliSeconds / 1000) ||
224 !X509_set_notBefore(certificate.get(), notBefore.get() /* Don't release; copied */))
225 return CertUtilsError::BoringSsl;
226
227 // Set expiration date.
228 time_t notAfterTime;
229 notAfterTime = (time_t)std::min((uint64_t)std::numeric_limits<time_t>::max(),
230 usageExpireDateTimeMilliSeconds / 1000);
231
232 ASN1_TIME_Ptr notAfter(ASN1_TIME_new());
233 if (!notAfter || !ASN1_TIME_set(notAfter.get(), notAfterTime) ||
234 !X509_set_notAfter(certificate.get(), notAfter.get() /* Don't release; copied */)) {
235 return CertUtilsError::BoringSsl;
236 }
237
238 return certificate;
239}
240
241std::variant<CertUtilsError, X509_Ptr>
Janis Danisevskis2c084012021-01-31 22:23:17 -0800242makeCert(const EVP_PKEY* evp_pkey,
243 std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,
244 std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800245 const uint64_t activeDateTimeMilliSeconds, const uint64_t usageExpireDateTimeMilliSeconds,
246 bool addSubjectKeyIdEx, std::optional<KeyUsageExtension> keyUsageEx,
247 std::optional<BasicConstraintsExtension> basicConstraints) {
248
249 // Make the rump certificate with serial, subject, not before and not after dates.
250 auto certificateV =
251 makeCertRump(serial, subject, activeDateTimeMilliSeconds, usageExpireDateTimeMilliSeconds);
252 if (auto error = std::get_if<CertUtilsError>(&certificateV)) {
253 return *error;
254 }
255 auto certificate = std::move(std::get<X509_Ptr>(certificateV));
256
257 // Set the public key.
258 if (!X509_set_pubkey(certificate.get(), const_cast<EVP_PKEY*>(evp_pkey))) {
259 return CertUtilsError::BoringSsl;
260 }
261
262 if (keyUsageEx) {
263 // Make and add the key usage extension.
264 auto key_usage_extensionV = makeKeyUsageExtension(
265 keyUsageEx->isSigningKey, keyUsageEx->isEncryptionKey, keyUsageEx->isCertificationKey);
266 if (auto error = std::get_if<CertUtilsError>(&key_usage_extensionV)) {
267 return *error;
268 }
269 auto key_usage_extension = std::move(std::get<ASN1_BIT_STRING_Ptr>(key_usage_extensionV));
270 if (!X509_add1_ext_i2d(certificate.get(), NID_key_usage,
271 key_usage_extension.get() /* Don't release; copied */,
272 true /* critical */, 0 /* flags */)) {
273 return CertUtilsError::BoringSsl;
274 }
275 }
276
277 if (basicConstraints) {
278 // Make and add basic constraints
279 auto basic_constraints_extensionV =
280 makeBasicConstraintsExtension(basicConstraints->isCa, basicConstraints->pathLength);
281 if (auto error = std::get_if<CertUtilsError>(&basic_constraints_extensionV)) {
282 return *error;
283 }
284 auto basic_constraints_extension =
285 std::move(std::get<BASIC_CONSTRAINTS_Ptr>(basic_constraints_extensionV));
286 if (!X509_add1_ext_i2d(certificate.get(), NID_basic_constraints,
287 basic_constraints_extension.get() /* Don't release; copied */,
288 true /* critical */, 0 /* flags */)) {
289 return CertUtilsError::BoringSsl;
290 }
291 }
292
293 if (addSubjectKeyIdEx) {
294 // Make and add subject key id extension.
295 auto keyidV = makeKeyId(certificate.get());
296 if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
297 return *error;
298 }
299 auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
300
301 auto subject_key_extensionV = makeSubjectKeyExtension(keyid);
302 if (auto error = std::get_if<CertUtilsError>(&subject_key_extensionV)) {
303 return *error;
304 }
305 auto subject_key_extension =
306 std::move(std::get<ASN1_OCTET_STRING_Ptr>(subject_key_extensionV));
307 if (!X509_add1_ext_i2d(certificate.get(), NID_subject_key_identifier,
308 subject_key_extension.get() /* Don't release; copied */,
309 false /* critical */, 0 /* flags */)) {
310 return CertUtilsError::BoringSsl;
311 }
312 }
313
314 return certificate;
315}
316
317CertUtilsError setIssuer(X509* cert, const X509* signingCert, bool addAuthKeyExt) {
318
319 X509_NAME* issuerName(X509_get_subject_name(signingCert));
320
321 // Set Issuer Name
322 if (issuerName) {
323 if (!X509_set_issuer_name(cert, issuerName /* copied */)) {
324 return CertUtilsError::BoringSsl;
325 }
326 } else {
327 return CertUtilsError::Encoding;
328 }
329
330 if (addAuthKeyExt) {
331 // Make and add authority key extension - self signed.
332 auto keyidV = makeKeyId(signingCert);
333 if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
334 return *error;
335 }
336 auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
337
338 auto auth_key_extensionV = makeAuthorityKeyExtension(keyid);
339 if (auto error = std::get_if<CertUtilsError>(&auth_key_extensionV)) {
340 return *error;
341 }
342 auto auth_key_extension = std::move(std::get<AUTHORITY_KEYID_Ptr>(auth_key_extensionV));
343 if (!X509_add1_ext_i2d(cert, NID_authority_key_identifier, auth_key_extension.get(), false,
344 0)) {
345 return CertUtilsError::BoringSsl;
346 }
347 }
348 return CertUtilsError::Ok;
349}
350
351// Takes a certificate a signing certificate and the raw private signing_key. And signs
352// the certificate with the latter.
353CertUtilsError signCert(X509* certificate, EVP_PKEY* signing_key) {
354
355 if (certificate == nullptr) {
356 return CertUtilsError::UnexpectedNullPointer;
357 }
358
359 if (!X509_sign(certificate, signing_key, EVP_sha256())) {
360 return CertUtilsError::BoringSsl;
361 }
362
363 return CertUtilsError::Ok;
364}
365
366std::variant<CertUtilsError, std::vector<uint8_t>> encodeCert(X509* certificate) {
367 int len = i2d_X509(certificate, nullptr);
368 if (len < 0) {
369 return CertUtilsError::BoringSsl;
370 }
371
372 auto result = std::vector<uint8_t>(len);
373 uint8_t* p = result.data();
374
375 if (i2d_X509(certificate, &p) < 0) {
376 return CertUtilsError::BoringSsl;
377 }
378 return result;
379}
380
381CertUtilsError setRsaDigestAlgorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
382 if (alg_ptr == nullptr || digest == nullptr) {
383 return CertUtilsError::UnexpectedNullPointer;
384 }
385 *alg_ptr = X509_ALGOR_new();
386 if (*alg_ptr == nullptr) {
387 return CertUtilsError::MemoryAllocation;
388 }
389 X509_ALGOR_set_md(*alg_ptr, digest);
390 return CertUtilsError::Ok;
391}
392
393CertUtilsError setPssMaskGeneratorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
394 X509_ALGOR* mgf1_digest = nullptr;
395 if (auto error = setRsaDigestAlgorField(&mgf1_digest, digest)) {
396 return error;
397 }
398 X509_ALGOR_Ptr mgf1_digest_ptr(mgf1_digest);
399
400 ASN1_OCTET_STRING* mgf1_digest_algor_str = nullptr;
401 if (!ASN1_item_pack(mgf1_digest, ASN1_ITEM_rptr(X509_ALGOR), &mgf1_digest_algor_str)) {
402 return CertUtilsError::Encoding;
403 }
404 ASN1_OCTET_STRING_Ptr mgf1_digest_algor_str_ptr(mgf1_digest_algor_str);
405
406 *alg_ptr = X509_ALGOR_new();
407 if (*alg_ptr == nullptr) {
408 return CertUtilsError::MemoryAllocation;
409 }
410 X509_ALGOR_set0(*alg_ptr, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, mgf1_digest_algor_str);
411 // *alg_ptr took ownership of the octet string
412 mgf1_digest_algor_str_ptr.release();
413 return CertUtilsError::Ok;
414}
415
416static CertUtilsError setSaltLength(RSA_PSS_PARAMS* pss_params, unsigned length) {
417 pss_params->saltLength = ASN1_INTEGER_new();
418 if (pss_params->saltLength == nullptr) {
419 return CertUtilsError::MemoryAllocation;
420 }
421 if (!ASN1_INTEGER_set(pss_params->saltLength, length)) {
422 return CertUtilsError::Encoding;
423 };
424 return CertUtilsError::Ok;
425}
426
427std::variant<CertUtilsError, ASN1_STRING_Ptr> buildRsaPssParameter(Digest digest) {
428 RSA_PSS_PARAMS_Ptr pss(RSA_PSS_PARAMS_new());
429 if (!pss) {
430 return CertUtilsError::MemoryAllocation;
431 }
432
433 const EVP_MD* md = nullptr;
434
435 switch (digest) {
436 case Digest::SHA1:
437 break;
438 case Digest::SHA224:
439 md = EVP_sha224();
440 break;
441 case Digest::SHA256:
442 md = EVP_sha256();
443 break;
444 case Digest::SHA384:
445 md = EVP_sha384();
446 break;
447 case Digest::SHA512:
448 md = EVP_sha512();
449 break;
450 default:
451 return CertUtilsError::InvalidArgument;
452 }
453
454 if (md != nullptr) {
455 if (auto error = setSaltLength(pss.get(), EVP_MD_size(md))) {
456 return error;
457 }
458 if (auto error = setRsaDigestAlgorField(&pss->hashAlgorithm, md)) {
459 return error;
460 }
461 if (auto error = setPssMaskGeneratorField(&pss->maskGenAlgorithm, md)) {
462 return error;
463 }
464 }
465
466 ASN1_STRING* algo_str = nullptr;
467 if (!ASN1_item_pack(pss.get(), ASN1_ITEM_rptr(RSA_PSS_PARAMS), &algo_str)) {
468 return CertUtilsError::BoringSsl;
469 }
470
471 return ASN1_STRING_Ptr(algo_str);
472}
473
474CertUtilsError makeAndSetAlgo(X509_ALGOR* algo_field, Algo algo, Padding padding, Digest digest) {
475 if (algo_field == nullptr) {
476 return CertUtilsError::UnexpectedNullPointer;
477 }
478 ASN1_STRING_Ptr param;
479 int param_type = V_ASN1_UNDEF;
480 int nid = 0;
481 switch (algo) {
482 case Algo::ECDSA:
483 switch (digest) {
484 case Digest::SHA1:
485 nid = NID_ecdsa_with_SHA1;
486 break;
487 case Digest::SHA224:
488 nid = NID_ecdsa_with_SHA224;
489 break;
490 case Digest::SHA256:
491 nid = NID_ecdsa_with_SHA256;
492 break;
493 case Digest::SHA384:
494 nid = NID_ecdsa_with_SHA384;
495 break;
496 case Digest::SHA512:
497 nid = NID_ecdsa_with_SHA512;
498 break;
499 default:
500 return CertUtilsError::InvalidArgument;
501 }
502 break;
503 case Algo::RSA:
504 switch (padding) {
505 case Padding::PKCS1_5:
506 param_type = V_ASN1_NULL;
507 switch (digest) {
508 case Digest::SHA1:
509 nid = NID_sha1WithRSAEncryption;
510 break;
511 case Digest::SHA224:
512 nid = NID_sha224WithRSAEncryption;
513 break;
514 case Digest::SHA256:
515 nid = NID_sha256WithRSAEncryption;
516 break;
517 case Digest::SHA384:
518 nid = NID_sha384WithRSAEncryption;
519 break;
520 case Digest::SHA512:
521 nid = NID_sha512WithRSAEncryption;
522 break;
523 default:
524 return CertUtilsError::InvalidArgument;
525 }
526 break;
527 case Padding::PSS: {
528 auto v = buildRsaPssParameter(digest);
529 if (auto param_str = std::get_if<ASN1_STRING_Ptr>(&v)) {
530 param = std::move(*param_str);
531 param_type = V_ASN1_SEQUENCE;
532 nid = NID_rsassaPss;
533 } else {
534 return std::get<CertUtilsError>(v);
535 }
536 break;
537 }
538 default:
539 return CertUtilsError::InvalidArgument;
540 }
541 break;
542 default:
543 return CertUtilsError::InvalidArgument;
544 }
545
546 if (!X509_ALGOR_set0(algo_field, OBJ_nid2obj(nid), param_type, param.get())) {
547 return CertUtilsError::Encoding;
548 }
549 // The X509 struct took ownership.
550 param.release();
551 return CertUtilsError::Ok;
552}
553
554// This function allows for signing a
555CertUtilsError signCertWith(X509* certificate,
556 std::function<std::vector<uint8_t>(const uint8_t*, size_t)> sign,
557 Algo algo, Padding padding, Digest digest) {
558 if (auto error = makeAndSetAlgo(certificate->sig_alg, algo, padding, digest)) {
559 return error;
560 }
561 if (auto error = makeAndSetAlgo(certificate->cert_info->signature, algo, padding, digest)) {
562 return error;
563 }
564
565 uint8_t* cert_buf = nullptr;
Greg Kaiser9b9704f2020-11-19 16:24:30 -0800566 int buf_len = i2d_re_X509_tbs(certificate, &cert_buf);
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800567 if (buf_len < 0) {
568 return CertUtilsError::Encoding;
569 }
570
571 bssl::UniquePtr<uint8_t> free_cert_buf(cert_buf);
572 auto signature = sign(cert_buf, buf_len);
Janis Danisevskisdc502d12021-01-15 08:52:12 -0800573 if (signature.empty()) {
574 return CertUtilsError::SignatureFailed;
575 }
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800576
577 if (!ASN1_STRING_set(certificate->signature, signature.data(), signature.size())) {
578 return CertUtilsError::BoringSsl;
579 }
580
581 certificate->signature->flags &= ~(0x07);
582 certificate->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
583
584 return CertUtilsError::Ok;
585}
586
587} // namespace keystore