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