• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 <variant>
27 #include <vector>
28 
29 #ifndef __LP64__
30 #include <time64.h>
31 #endif
32 
33 namespace keystore {
34 
35 namespace {
36 
37 constexpr int kDigitalSignatureKeyUsageBit = 0;
38 constexpr int kKeyEnciphermentKeyUsageBit = 2;
39 constexpr int kDataEnciphermentKeyUsageBit = 3;
40 constexpr int kKeyCertSignBit = 5;
41 constexpr int kMaxKeyUsageBit = 8;
42 
43 DEFINE_OPENSSL_OBJECT_POINTER(ASN1_STRING);
44 DEFINE_OPENSSL_OBJECT_POINTER(RSA_PSS_PARAMS);
45 DEFINE_OPENSSL_OBJECT_POINTER(AUTHORITY_KEYID);
46 DEFINE_OPENSSL_OBJECT_POINTER(BASIC_CONSTRAINTS);
47 DEFINE_OPENSSL_OBJECT_POINTER(X509_ALGOR);
48 DEFINE_OPENSSL_OBJECT_POINTER(BIGNUM);
49 
50 }  // namespace
51 
52 constexpr const char kDefaultCommonName[] = "Default Common Name";
53 
54 std::variant<CertUtilsError, X509_NAME_Ptr>
makeCommonName(std::optional<std::reference_wrapper<const std::vector<uint8_t>>> name)55 makeCommonName(std::optional<std::reference_wrapper<const std::vector<uint8_t>>> name) {
56     if (name) {
57         const uint8_t* p = name->get().data();
58         X509_NAME_Ptr x509_name(d2i_X509_NAME(nullptr, &p, name->get().size()));
59         if (!x509_name) {
60             return CertUtilsError::MemoryAllocation;
61         }
62         return x509_name;
63     }
64 
65     X509_NAME_Ptr x509_name(X509_NAME_new());
66     if (!x509_name) {
67         return CertUtilsError::MemoryAllocation;
68     }
69     if (!X509_NAME_add_entry_by_txt(x509_name.get(), "CN", MBSTRING_ASC,
70                                     reinterpret_cast<const uint8_t*>(kDefaultCommonName),
71                                     sizeof(kDefaultCommonName) - 1, -1 /* loc */, 0 /* set */)) {
72         return CertUtilsError::BoringSsl;
73     }
74     return x509_name;
75 }
76 
makeKeyId(const X509 * cert)77 std::variant<CertUtilsError, std::vector<uint8_t>> makeKeyId(const X509* cert) {
78     std::vector<uint8_t> keyid(20);
79     unsigned int len;
80     if (!X509_pubkey_digest(cert, EVP_sha1(), keyid.data(), &len)) {
81         return CertUtilsError::Encoding;
82     }
83     return keyid;
84 }
85 
86 std::variant<CertUtilsError, AUTHORITY_KEYID_Ptr>
makeAuthorityKeyExtension(const std::vector<uint8_t> & keyid)87 makeAuthorityKeyExtension(const std::vector<uint8_t>& keyid) {
88     AUTHORITY_KEYID_Ptr auth_key(AUTHORITY_KEYID_new());
89     if (!auth_key) {
90         return CertUtilsError::MemoryAllocation;
91     }
92 
93     auth_key->keyid = ASN1_OCTET_STRING_new();
94     if (auth_key->keyid == nullptr) {
95         return CertUtilsError::MemoryAllocation;
96     }
97 
98     if (!ASN1_OCTET_STRING_set(auth_key->keyid, keyid.data(), keyid.size())) {
99         return CertUtilsError::BoringSsl;
100     }
101 
102     return auth_key;
103 }
104 
105 std::variant<CertUtilsError, ASN1_OCTET_STRING_Ptr>
makeSubjectKeyExtension(const std::vector<uint8_t> & keyid)106 makeSubjectKeyExtension(const std::vector<uint8_t>& keyid) {
107 
108     // Build OCTET_STRING
109     ASN1_OCTET_STRING_Ptr keyid_str(ASN1_OCTET_STRING_new());
110     if (!keyid_str || !ASN1_OCTET_STRING_set(keyid_str.get(), keyid.data(), keyid.size())) {
111         return CertUtilsError::BoringSsl;
112     }
113 
114     return keyid_str;
115 }
116 
117 std::variant<CertUtilsError, BASIC_CONSTRAINTS_Ptr>
makeBasicConstraintsExtension(bool is_ca,std::optional<int> path_length)118 makeBasicConstraintsExtension(bool is_ca, std::optional<int> path_length) {
119 
120     BASIC_CONSTRAINTS_Ptr bcons(BASIC_CONSTRAINTS_new());
121     if (!bcons) {
122         return CertUtilsError::MemoryAllocation;
123     }
124 
125     bcons->ca = is_ca;
126     bcons->pathlen = nullptr;
127     if (path_length) {
128         bcons->pathlen = ASN1_INTEGER_new();
129         if (bcons->pathlen == nullptr || !ASN1_INTEGER_set(bcons->pathlen, *path_length)) {
130             return CertUtilsError::BoringSsl;
131         }
132     }
133 
134     return bcons;
135 }
136 
137 std::variant<CertUtilsError, ASN1_BIT_STRING_Ptr>
makeKeyUsageExtension(bool is_signing_key,bool is_encryption_key,bool is_cert_key)138 makeKeyUsageExtension(bool is_signing_key, bool is_encryption_key, bool is_cert_key) {
139     // Build BIT_STRING with correct contents.
140     ASN1_BIT_STRING_Ptr key_usage(ASN1_BIT_STRING_new());
141     if (!key_usage) {
142         return CertUtilsError::BoringSsl;
143     }
144 
145     for (size_t i = 0; i <= kMaxKeyUsageBit; ++i) {
146         if (!ASN1_BIT_STRING_set_bit(key_usage.get(), i, 0)) {
147             return CertUtilsError::BoringSsl;
148         }
149     }
150 
151     if (is_signing_key) {
152         if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kDigitalSignatureKeyUsageBit, 1)) {
153             return CertUtilsError::BoringSsl;
154         }
155     }
156 
157     if (is_encryption_key) {
158         if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyEnciphermentKeyUsageBit, 1) ||
159             !ASN1_BIT_STRING_set_bit(key_usage.get(), kDataEnciphermentKeyUsageBit, 1)) {
160             return CertUtilsError::BoringSsl;
161         }
162     }
163 
164     if (is_cert_key) {
165         if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyCertSignBit, 1)) {
166             return CertUtilsError::BoringSsl;
167         }
168     }
169 
170     return key_usage;
171 }
172 
173 // TODO Once boring ssl can take int64_t instead of time_t we can go back to using
174 //      ASN1_TIME_set: https://bugs.chromium.org/p/boringssl/issues/detail?id=416
toTimeString(int64_t timeMillis)175 std::optional<std::array<char, 16>> toTimeString(int64_t timeMillis) {
176     struct tm time;
177     // If timeMillis is negative the rounding direction should still be to the nearest previous
178     // second.
179     if (timeMillis < 0 && __builtin_add_overflow(timeMillis, -999, &timeMillis)) {
180         return std::nullopt;
181     }
182 #if defined(__LP64__)
183     time_t timeSeconds = timeMillis / 1000;
184     if (gmtime_r(&timeSeconds, &time) == nullptr) {
185         return std::nullopt;
186     }
187 #else
188     time64_t timeSeconds = timeMillis / 1000;
189     if (gmtime64_r(&timeSeconds, &time) == nullptr) {
190         return std::nullopt;
191     }
192 #endif
193     std::array<char, 16> buffer;
194     if (__builtin_add_overflow(time.tm_year, 1900, &time.tm_year)) {
195         return std::nullopt;
196     }
197     if (time.tm_year >= 1950 && time.tm_year < 2050) {
198         // UTCTime according to RFC5280 4.1.2.5.1.
199         snprintf(buffer.data(), buffer.size(), "%02d%02d%02d%02d%02d%02dZ", time.tm_year % 100,
200                  time.tm_mon + 1, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec);
201     } else if (time.tm_year >= 0 && time.tm_year < 10000) {
202         // GeneralizedTime according to RFC5280 4.1.2.5.2.
203         snprintf(buffer.data(), buffer.size(), "%04d%02d%02d%02d%02d%02dZ", time.tm_year,
204                  time.tm_mon + 1, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec);
205     } else {
206         return std::nullopt;
207     }
208     return buffer;
209 }
210 
211 // Creates a rump certificate structure with serial, subject and issuer names, as well as
212 // activation and expiry date.
213 // Callers should pass an empty X509_Ptr and check the return value for CertUtilsError::Ok (0)
214 // before accessing the result.
215 std::variant<CertUtilsError, X509_Ptr>
makeCertRump(std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,const int64_t activeDateTimeMilliSeconds,const int64_t usageExpireDateTimeMilliSeconds)216 makeCertRump(std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,
217              std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,
218              const int64_t activeDateTimeMilliSeconds,
219              const int64_t usageExpireDateTimeMilliSeconds) {
220 
221     // Create certificate structure.
222     X509_Ptr certificate(X509_new());
223     if (!certificate) {
224         return CertUtilsError::BoringSsl;
225     }
226 
227     // Set the X509 version.
228     if (!X509_set_version(certificate.get(), 2 /* version 3, but zero-based */)) {
229         return CertUtilsError::BoringSsl;
230     }
231 
232     BIGNUM_Ptr bn_serial;
233     if (serial) {
234         bn_serial = BIGNUM_Ptr(BN_bin2bn(serial->get().data(), serial->get().size(), nullptr));
235         if (!bn_serial) {
236             return CertUtilsError::MemoryAllocation;
237         }
238     } else {
239         bn_serial = BIGNUM_Ptr(BN_new());
240         if (!bn_serial) {
241             return CertUtilsError::MemoryAllocation;
242         }
243         BN_zero(bn_serial.get());
244     }
245 
246     // Set the certificate serialNumber
247     ASN1_INTEGER_Ptr serialNumber(ASN1_INTEGER_new());
248     if (!serialNumber || !BN_to_ASN1_INTEGER(bn_serial.get(), serialNumber.get()) ||
249         !X509_set_serialNumber(certificate.get(), serialNumber.get() /* Don't release; copied */))
250         return CertUtilsError::BoringSsl;
251 
252     // Set Subject Name
253     auto subjectName = makeCommonName(subject);
254     if (auto x509_subject = std::get_if<X509_NAME_Ptr>(&subjectName)) {
255         if (!X509_set_subject_name(certificate.get(), x509_subject->get() /* copied */)) {
256             return CertUtilsError::BoringSsl;
257         }
258     } else {
259         return std::get<CertUtilsError>(subjectName);
260     }
261 
262     auto notBeforeTime = toTimeString(activeDateTimeMilliSeconds);
263     if (!notBeforeTime) {
264         return CertUtilsError::TimeError;
265     }
266     // Set activation date.
267     ASN1_TIME_Ptr notBefore(ASN1_TIME_new());
268     if (!notBefore || !ASN1_TIME_set_string(notBefore.get(), notBeforeTime->data()) ||
269         !X509_set_notBefore(certificate.get(), notBefore.get() /* Don't release; copied */))
270         return CertUtilsError::BoringSsl;
271 
272     // Set expiration date.
273     auto notAfterTime = toTimeString(usageExpireDateTimeMilliSeconds);
274     if (!notAfterTime) {
275         return CertUtilsError::TimeError;
276     }
277 
278     ASN1_TIME_Ptr notAfter(ASN1_TIME_new());
279     if (!notAfter || !ASN1_TIME_set_string(notAfter.get(), notAfterTime->data()) ||
280         !X509_set_notAfter(certificate.get(), notAfter.get() /* Don't release; copied */)) {
281         return CertUtilsError::BoringSsl;
282     }
283 
284     return certificate;
285 }
286 
287 std::variant<CertUtilsError, X509_Ptr>
makeCert(const EVP_PKEY * evp_pkey,std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,const int64_t activeDateTimeMilliSeconds,const int64_t usageExpireDateTimeMilliSeconds,bool addSubjectKeyIdEx,std::optional<KeyUsageExtension> keyUsageEx,std::optional<BasicConstraintsExtension> basicConstraints)288 makeCert(const EVP_PKEY* evp_pkey,
289          std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,
290          std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,
291          const int64_t activeDateTimeMilliSeconds, const int64_t usageExpireDateTimeMilliSeconds,
292          bool addSubjectKeyIdEx, std::optional<KeyUsageExtension> keyUsageEx,
293          std::optional<BasicConstraintsExtension> basicConstraints) {
294 
295     // Make the rump certificate with serial, subject, not before and not after dates.
296     auto certificateV =
297         makeCertRump(serial, subject, activeDateTimeMilliSeconds, usageExpireDateTimeMilliSeconds);
298     if (auto error = std::get_if<CertUtilsError>(&certificateV)) {
299         return *error;
300     }
301     auto certificate = std::move(std::get<X509_Ptr>(certificateV));
302 
303     // Set the public key.
304     if (!X509_set_pubkey(certificate.get(), const_cast<EVP_PKEY*>(evp_pkey))) {
305         return CertUtilsError::BoringSsl;
306     }
307 
308     if (keyUsageEx) {
309         // Make and add the key usage extension.
310         auto key_usage_extensionV = makeKeyUsageExtension(
311             keyUsageEx->isSigningKey, keyUsageEx->isEncryptionKey, keyUsageEx->isCertificationKey);
312         if (auto error = std::get_if<CertUtilsError>(&key_usage_extensionV)) {
313             return *error;
314         }
315         auto key_usage_extension = std::move(std::get<ASN1_BIT_STRING_Ptr>(key_usage_extensionV));
316         if (!X509_add1_ext_i2d(certificate.get(), NID_key_usage,
317                                key_usage_extension.get() /* Don't release; copied */,
318                                true /* critical */, 0 /* flags */)) {
319             return CertUtilsError::BoringSsl;
320         }
321     }
322 
323     if (basicConstraints) {
324         // Make and add basic constraints
325         auto basic_constraints_extensionV =
326             makeBasicConstraintsExtension(basicConstraints->isCa, basicConstraints->pathLength);
327         if (auto error = std::get_if<CertUtilsError>(&basic_constraints_extensionV)) {
328             return *error;
329         }
330         auto basic_constraints_extension =
331             std::move(std::get<BASIC_CONSTRAINTS_Ptr>(basic_constraints_extensionV));
332         if (!X509_add1_ext_i2d(certificate.get(), NID_basic_constraints,
333                                basic_constraints_extension.get() /* Don't release; copied */,
334                                true /* critical */, 0 /* flags */)) {
335             return CertUtilsError::BoringSsl;
336         }
337     }
338 
339     if (addSubjectKeyIdEx) {
340         // Make and add subject key id extension.
341         auto keyidV = makeKeyId(certificate.get());
342         if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
343             return *error;
344         }
345         auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
346 
347         auto subject_key_extensionV = makeSubjectKeyExtension(keyid);
348         if (auto error = std::get_if<CertUtilsError>(&subject_key_extensionV)) {
349             return *error;
350         }
351         auto subject_key_extension =
352             std::move(std::get<ASN1_OCTET_STRING_Ptr>(subject_key_extensionV));
353         if (!X509_add1_ext_i2d(certificate.get(), NID_subject_key_identifier,
354                                subject_key_extension.get() /* Don't release; copied */,
355                                false /* critical */, 0 /* flags */)) {
356             return CertUtilsError::BoringSsl;
357         }
358     }
359 
360     return certificate;
361 }
362 
setIssuer(X509 * cert,const X509 * signingCert,bool addAuthKeyExt)363 CertUtilsError setIssuer(X509* cert, const X509* signingCert, bool addAuthKeyExt) {
364 
365     X509_NAME* issuerName(X509_get_subject_name(signingCert));
366 
367     // Set Issuer Name
368     if (issuerName) {
369         if (!X509_set_issuer_name(cert, issuerName /* copied */)) {
370             return CertUtilsError::BoringSsl;
371         }
372     } else {
373         return CertUtilsError::Encoding;
374     }
375 
376     if (addAuthKeyExt) {
377         // Make and add authority key extension - self signed.
378         auto keyidV = makeKeyId(signingCert);
379         if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
380             return *error;
381         }
382         auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
383 
384         auto auth_key_extensionV = makeAuthorityKeyExtension(keyid);
385         if (auto error = std::get_if<CertUtilsError>(&auth_key_extensionV)) {
386             return *error;
387         }
388         auto auth_key_extension = std::move(std::get<AUTHORITY_KEYID_Ptr>(auth_key_extensionV));
389         if (!X509_add1_ext_i2d(cert, NID_authority_key_identifier, auth_key_extension.get(), false,
390                                0)) {
391             return CertUtilsError::BoringSsl;
392         }
393     }
394     return CertUtilsError::Ok;
395 }
396 
397 // Takes a certificate a signing certificate and the raw private signing_key. And signs
398 // the certificate with the latter.
signCert(X509 * certificate,EVP_PKEY * signing_key)399 CertUtilsError signCert(X509* certificate, EVP_PKEY* signing_key) {
400 
401     if (certificate == nullptr) {
402         return CertUtilsError::UnexpectedNullPointer;
403     }
404 
405     if (!X509_sign(certificate, signing_key, EVP_sha256())) {
406         return CertUtilsError::BoringSsl;
407     }
408 
409     return CertUtilsError::Ok;
410 }
411 
encodeCert(X509 * certificate)412 std::variant<CertUtilsError, std::vector<uint8_t>> encodeCert(X509* certificate) {
413     int len = i2d_X509(certificate, nullptr);
414     if (len < 0) {
415         return CertUtilsError::BoringSsl;
416     }
417 
418     auto result = std::vector<uint8_t>(len);
419     uint8_t* p = result.data();
420 
421     if (i2d_X509(certificate, &p) < 0) {
422         return CertUtilsError::BoringSsl;
423     }
424     return result;
425 }
426 
setRsaDigestAlgorField(X509_ALGOR ** alg_ptr,const EVP_MD * digest)427 CertUtilsError setRsaDigestAlgorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
428     if (alg_ptr == nullptr || digest == nullptr) {
429         return CertUtilsError::UnexpectedNullPointer;
430     }
431     *alg_ptr = X509_ALGOR_new();
432     if (*alg_ptr == nullptr) {
433         return CertUtilsError::MemoryAllocation;
434     }
435     X509_ALGOR_set_md(*alg_ptr, digest);
436     return CertUtilsError::Ok;
437 }
438 
setPssMaskGeneratorField(X509_ALGOR ** alg_ptr,const EVP_MD * digest)439 CertUtilsError setPssMaskGeneratorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
440     X509_ALGOR* mgf1_digest = nullptr;
441     if (auto error = setRsaDigestAlgorField(&mgf1_digest, digest)) {
442         return error;
443     }
444     X509_ALGOR_Ptr mgf1_digest_ptr(mgf1_digest);
445 
446     ASN1_OCTET_STRING* mgf1_digest_algor_str = nullptr;
447     if (!ASN1_item_pack(mgf1_digest, ASN1_ITEM_rptr(X509_ALGOR), &mgf1_digest_algor_str)) {
448         return CertUtilsError::Encoding;
449     }
450     ASN1_OCTET_STRING_Ptr mgf1_digest_algor_str_ptr(mgf1_digest_algor_str);
451 
452     *alg_ptr = X509_ALGOR_new();
453     if (*alg_ptr == nullptr) {
454         return CertUtilsError::MemoryAllocation;
455     }
456     X509_ALGOR_set0(*alg_ptr, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, mgf1_digest_algor_str);
457     // *alg_ptr took ownership of the octet string
458     mgf1_digest_algor_str_ptr.release();
459     return CertUtilsError::Ok;
460 }
461 
setSaltLength(RSA_PSS_PARAMS * pss_params,unsigned length)462 static CertUtilsError setSaltLength(RSA_PSS_PARAMS* pss_params, unsigned length) {
463     pss_params->saltLength = ASN1_INTEGER_new();
464     if (pss_params->saltLength == nullptr) {
465         return CertUtilsError::MemoryAllocation;
466     }
467     if (!ASN1_INTEGER_set(pss_params->saltLength, length)) {
468         return CertUtilsError::Encoding;
469     };
470     return CertUtilsError::Ok;
471 }
472 
buildRsaPssParameter(Digest digest)473 std::variant<CertUtilsError, ASN1_STRING_Ptr> buildRsaPssParameter(Digest digest) {
474     RSA_PSS_PARAMS_Ptr pss(RSA_PSS_PARAMS_new());
475     if (!pss) {
476         return CertUtilsError::MemoryAllocation;
477     }
478 
479     const EVP_MD* md = nullptr;
480 
481     switch (digest) {
482     case Digest::SHA1:
483         break;
484     case Digest::SHA224:
485         md = EVP_sha224();
486         break;
487     case Digest::SHA256:
488         md = EVP_sha256();
489         break;
490     case Digest::SHA384:
491         md = EVP_sha384();
492         break;
493     case Digest::SHA512:
494         md = EVP_sha512();
495         break;
496     default:
497         return CertUtilsError::InvalidArgument;
498     }
499 
500     if (md != nullptr) {
501         if (auto error = setSaltLength(pss.get(), EVP_MD_size(md))) {
502             return error;
503         }
504         if (auto error = setRsaDigestAlgorField(&pss->hashAlgorithm, md)) {
505             return error;
506         }
507         if (auto error = setPssMaskGeneratorField(&pss->maskGenAlgorithm, md)) {
508             return error;
509         }
510     }
511 
512     ASN1_STRING* algo_str = nullptr;
513     if (!ASN1_item_pack(pss.get(), ASN1_ITEM_rptr(RSA_PSS_PARAMS), &algo_str)) {
514         return CertUtilsError::BoringSsl;
515     }
516 
517     return ASN1_STRING_Ptr(algo_str);
518 }
519 
makeAndSetAlgo(X509_ALGOR * algo_field,Algo algo,Padding padding,Digest digest)520 CertUtilsError makeAndSetAlgo(X509_ALGOR* algo_field, Algo algo, Padding padding, Digest digest) {
521     if (algo_field == nullptr) {
522         return CertUtilsError::UnexpectedNullPointer;
523     }
524     ASN1_STRING_Ptr param;
525     int param_type = V_ASN1_UNDEF;
526     int nid = 0;
527     switch (algo) {
528     case Algo::ECDSA:
529         switch (digest) {
530         case Digest::SHA1:
531             nid = NID_ecdsa_with_SHA1;
532             break;
533         case Digest::SHA224:
534             nid = NID_ecdsa_with_SHA224;
535             break;
536         case Digest::SHA256:
537             nid = NID_ecdsa_with_SHA256;
538             break;
539         case Digest::SHA384:
540             nid = NID_ecdsa_with_SHA384;
541             break;
542         case Digest::SHA512:
543             nid = NID_ecdsa_with_SHA512;
544             break;
545         default:
546             return CertUtilsError::InvalidArgument;
547         }
548         break;
549     case Algo::RSA:
550         switch (padding) {
551         case Padding::PKCS1_5:
552             param_type = V_ASN1_NULL;
553             switch (digest) {
554             case Digest::SHA1:
555                 nid = NID_sha1WithRSAEncryption;
556                 break;
557             case Digest::SHA224:
558                 nid = NID_sha224WithRSAEncryption;
559                 break;
560             case Digest::SHA256:
561                 nid = NID_sha256WithRSAEncryption;
562                 break;
563             case Digest::SHA384:
564                 nid = NID_sha384WithRSAEncryption;
565                 break;
566             case Digest::SHA512:
567                 nid = NID_sha512WithRSAEncryption;
568                 break;
569             default:
570                 return CertUtilsError::InvalidArgument;
571             }
572             break;
573         case Padding::PSS: {
574             auto v = buildRsaPssParameter(digest);
575             if (auto param_str = std::get_if<ASN1_STRING_Ptr>(&v)) {
576                 param = std::move(*param_str);
577                 param_type = V_ASN1_SEQUENCE;
578                 nid = NID_rsassaPss;
579             } else {
580                 return std::get<CertUtilsError>(v);
581             }
582             break;
583         }
584         default:
585             return CertUtilsError::InvalidArgument;
586         }
587         break;
588     default:
589         return CertUtilsError::InvalidArgument;
590     }
591 
592     if (!X509_ALGOR_set0(algo_field, OBJ_nid2obj(nid), param_type, param.get())) {
593         return CertUtilsError::Encoding;
594     }
595     // The X509 struct took ownership.
596     param.release();
597     return CertUtilsError::Ok;
598 }
599 
600 // This function allows for signing a
signCertWith(X509 * certificate,std::function<std::vector<uint8_t> (const uint8_t *,size_t)> sign,Algo algo,Padding padding,Digest digest)601 CertUtilsError signCertWith(X509* certificate,
602                             std::function<std::vector<uint8_t>(const uint8_t*, size_t)> sign,
603                             Algo algo, Padding padding, Digest digest) {
604     if (auto error = makeAndSetAlgo(certificate->sig_alg, algo, padding, digest)) {
605         return error;
606     }
607     if (auto error = makeAndSetAlgo(certificate->cert_info->signature, algo, padding, digest)) {
608         return error;
609     }
610 
611     uint8_t* cert_buf = nullptr;
612     int buf_len = i2d_re_X509_tbs(certificate, &cert_buf);
613     if (buf_len < 0) {
614         return CertUtilsError::Encoding;
615     }
616 
617     bssl::UniquePtr<uint8_t> free_cert_buf(cert_buf);
618     auto signature = sign(cert_buf, buf_len);
619     if (signature.empty()) {
620         return CertUtilsError::SignatureFailed;
621     }
622 
623     if (!ASN1_STRING_set(certificate->signature, signature.data(), signature.size())) {
624         return CertUtilsError::BoringSsl;
625     }
626 
627     certificate->signature->flags &= ~(0x07);
628     certificate->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
629 
630     return CertUtilsError::Ok;
631 }
632 
633 }  // namespace keystore
634