blob: d0508c8cb28e5f9188f29b70d31feecca95e43e5 [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>
David Benjamin891b9542021-05-06 13:36:46 -040022#include <openssl/ossl_typ.h>
Janis Danisevskisa7c72db2020-11-05 12:02:22 -080023#include <openssl/x509v3.h>
24
25#include <functional>
26#include <limits>
27#include <string>
28#include <variant>
29#include <vector>
30
31namespace keystore {
32
33namespace {
34
35constexpr int kDigitalSignatureKeyUsageBit = 0;
36constexpr int kKeyEnciphermentKeyUsageBit = 2;
37constexpr int kDataEnciphermentKeyUsageBit = 3;
38constexpr int kKeyCertSignBit = 5;
39constexpr int kMaxKeyUsageBit = 8;
40
41DEFINE_OPENSSL_OBJECT_POINTER(ASN1_STRING);
42DEFINE_OPENSSL_OBJECT_POINTER(RSA_PSS_PARAMS);
43DEFINE_OPENSSL_OBJECT_POINTER(AUTHORITY_KEYID);
44DEFINE_OPENSSL_OBJECT_POINTER(BASIC_CONSTRAINTS);
45DEFINE_OPENSSL_OBJECT_POINTER(X509_ALGOR);
Janis Danisevskis2c084012021-01-31 22:23:17 -080046DEFINE_OPENSSL_OBJECT_POINTER(BIGNUM);
Janis Danisevskisa7c72db2020-11-05 12:02:22 -080047
48} // namespace
49
Janis Danisevskis2c084012021-01-31 22:23:17 -080050constexpr const char kDefaultCommonName[] = "Default Common Name";
51
52std::variant<CertUtilsError, X509_NAME_Ptr>
53makeCommonName(std::optional<std::reference_wrapper<const std::vector<uint8_t>>> name) {
54 if (name) {
55 const uint8_t* p = name->get().data();
56 X509_NAME_Ptr x509_name(d2i_X509_NAME(nullptr, &p, name->get().size()));
57 if (!x509_name) {
58 return CertUtilsError::MemoryAllocation;
59 }
60 return x509_name;
61 }
62
Janis Danisevskisa7c72db2020-11-05 12:02:22 -080063 X509_NAME_Ptr x509_name(X509_NAME_new());
64 if (!x509_name) {
Janis Danisevskis2c084012021-01-31 22:23:17 -080065 return CertUtilsError::MemoryAllocation;
Janis Danisevskisa7c72db2020-11-05 12:02:22 -080066 }
67 if (!X509_NAME_add_entry_by_txt(x509_name.get(), "CN", MBSTRING_ASC,
Janis Danisevskis2c084012021-01-31 22:23:17 -080068 reinterpret_cast<const uint8_t*>(kDefaultCommonName),
69 sizeof(kDefaultCommonName) - 1, -1 /* loc */, 0 /* set */)) {
Janis Danisevskisa7c72db2020-11-05 12:02:22 -080070 return CertUtilsError::BoringSsl;
71 }
72 return x509_name;
73}
74
75std::variant<CertUtilsError, std::vector<uint8_t>> makeKeyId(const X509* cert) {
76 std::vector<uint8_t> keyid(20);
77 unsigned int len;
78 if (!X509_pubkey_digest(cert, EVP_sha1(), keyid.data(), &len)) {
79 return CertUtilsError::Encoding;
80 }
81 return keyid;
82}
83
84std::variant<CertUtilsError, AUTHORITY_KEYID_Ptr>
85makeAuthorityKeyExtension(const std::vector<uint8_t>& keyid) {
86 AUTHORITY_KEYID_Ptr auth_key(AUTHORITY_KEYID_new());
87 if (!auth_key) {
88 return CertUtilsError::MemoryAllocation;
89 }
90
91 auth_key->keyid = ASN1_OCTET_STRING_new();
92 if (auth_key->keyid == nullptr) {
93 return CertUtilsError::MemoryAllocation;
94 }
95
96 if (!ASN1_OCTET_STRING_set(auth_key->keyid, keyid.data(), keyid.size())) {
97 return CertUtilsError::BoringSsl;
98 }
99
100 return auth_key;
101}
102
103std::variant<CertUtilsError, ASN1_OCTET_STRING_Ptr>
104makeSubjectKeyExtension(const std::vector<uint8_t>& keyid) {
105
106 // Build OCTET_STRING
107 ASN1_OCTET_STRING_Ptr keyid_str(ASN1_OCTET_STRING_new());
108 if (!keyid_str || !ASN1_OCTET_STRING_set(keyid_str.get(), keyid.data(), keyid.size())) {
109 return CertUtilsError::BoringSsl;
110 }
111
112 return keyid_str;
113}
114
115std::variant<CertUtilsError, BASIC_CONSTRAINTS_Ptr>
116makeBasicConstraintsExtension(bool is_ca, std::optional<int> path_length) {
117
118 BASIC_CONSTRAINTS_Ptr bcons(BASIC_CONSTRAINTS_new());
119 if (!bcons) {
120 return CertUtilsError::MemoryAllocation;
121 }
122
123 bcons->ca = is_ca;
124 bcons->pathlen = nullptr;
125 if (path_length) {
126 bcons->pathlen = ASN1_INTEGER_new();
127 if (bcons->pathlen == nullptr || !ASN1_INTEGER_set(bcons->pathlen, *path_length)) {
128 return CertUtilsError::BoringSsl;
129 }
130 }
131
132 return bcons;
133}
134
135std::variant<CertUtilsError, ASN1_BIT_STRING_Ptr>
136makeKeyUsageExtension(bool is_signing_key, bool is_encryption_key, bool is_cert_key) {
137 // Build BIT_STRING with correct contents.
138 ASN1_BIT_STRING_Ptr key_usage(ASN1_BIT_STRING_new());
139 if (!key_usage) {
140 return CertUtilsError::BoringSsl;
141 }
142
143 for (size_t i = 0; i <= kMaxKeyUsageBit; ++i) {
144 if (!ASN1_BIT_STRING_set_bit(key_usage.get(), i, 0)) {
145 return CertUtilsError::BoringSsl;
146 }
147 }
148
149 if (is_signing_key) {
150 if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kDigitalSignatureKeyUsageBit, 1)) {
151 return CertUtilsError::BoringSsl;
152 }
153 }
154
155 if (is_encryption_key) {
156 if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyEnciphermentKeyUsageBit, 1) ||
157 !ASN1_BIT_STRING_set_bit(key_usage.get(), kDataEnciphermentKeyUsageBit, 1)) {
158 return CertUtilsError::BoringSsl;
159 }
160 }
161
162 if (is_cert_key) {
163 if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyCertSignBit, 1)) {
164 return CertUtilsError::BoringSsl;
165 }
166 }
167
168 return key_usage;
169}
170
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800171template <typename Out, typename In> static Out saturate(In in) {
172 if constexpr (std::is_signed_v<Out> == std::is_signed_v<In>) {
173 if constexpr (sizeof(Out) >= sizeof(In)) {
174 // Same sign, and In fits into Out. Cast is lossless.
175 return static_cast<Out>(in);
176 } else {
177 // Out is smaller than In we may need to truncate.
178 // We pick the smaller of `out::max()` and the greater of `out::min()` and `in`.
179 return static_cast<Out>(
180 std::min(static_cast<In>(std::numeric_limits<Out>::max()),
181 std::max(static_cast<In>(std::numeric_limits<Out>::min()), in)));
182 }
183 } else {
184 // So we have different signs. This puts the lower bound at 0 because either input or output
185 // is unsigned. The upper bound is max of the smaller type or, if they are equal the max of
186 // the signed type.
187 if constexpr (std::is_signed_v<Out>) {
188 if constexpr (sizeof(Out) > sizeof(In)) {
189 return static_cast<Out>(in);
190 } else {
191 // Because `out` is the signed one, the lower bound of `in` is 0 and fits into
192 // `out`. We just have to compare the maximum and we do it in type In because it has
193 // a greater range than Out, so Out::max() is guaranteed to fit.
194 return static_cast<Out>(
195 std::min(static_cast<In>(std::numeric_limits<Out>::max()), in));
196 }
197 } else {
198 // Out is unsigned. So we can return 0 if in is negative.
199 if (in < 0) return 0;
200 if constexpr (sizeof(Out) >= sizeof(In)) {
201 // If Out is wider or equal we can assign lossless.
202 return static_cast<Out>(in);
203 } else {
204 // Otherwise we have to take the minimum of Out::max() and `in`.
205 return static_cast<Out>(
206 std::min(static_cast<In>(std::numeric_limits<Out>::max()), in));
207 }
208 }
209 }
210}
211
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800212// Creates a rump certificate structure with serial, subject and issuer names, as well as
213// activation and expiry date.
214// Callers should pass an empty X509_Ptr and check the return value for CertUtilsError::Ok (0)
215// before accessing the result.
216std::variant<CertUtilsError, X509_Ptr>
Janis Danisevskis2c084012021-01-31 22:23:17 -0800217makeCertRump(std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,
218 std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800219 const int64_t activeDateTimeMilliSeconds,
220 const int64_t usageExpireDateTimeMilliSeconds) {
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800221
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800222 // Create certificate structure.
223 X509_Ptr certificate(X509_new());
224 if (!certificate) {
225 return CertUtilsError::BoringSsl;
226 }
227
228 // Set the X509 version.
229 if (!X509_set_version(certificate.get(), 2 /* version 3, but zero-based */)) {
230 return CertUtilsError::BoringSsl;
231 }
232
Janis Danisevskis2c084012021-01-31 22:23:17 -0800233 BIGNUM_Ptr bn_serial;
234 if (serial) {
235 bn_serial = BIGNUM_Ptr(BN_bin2bn(serial->get().data(), serial->get().size(), nullptr));
236 if (!bn_serial) {
237 return CertUtilsError::MemoryAllocation;
238 }
239 } else {
240 bn_serial = BIGNUM_Ptr(BN_new());
241 if (!bn_serial) {
242 return CertUtilsError::MemoryAllocation;
243 }
244 BN_zero(bn_serial.get());
245 }
246
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800247 // Set the certificate serialNumber
248 ASN1_INTEGER_Ptr serialNumber(ASN1_INTEGER_new());
Janis Danisevskis2c084012021-01-31 22:23:17 -0800249 if (!serialNumber || !BN_to_ASN1_INTEGER(bn_serial.get(), serialNumber.get()) ||
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800250 !X509_set_serialNumber(certificate.get(), serialNumber.get() /* Don't release; copied */))
251 return CertUtilsError::BoringSsl;
252
253 // Set Subject Name
254 auto subjectName = makeCommonName(subject);
255 if (auto x509_subject = std::get_if<X509_NAME_Ptr>(&subjectName)) {
256 if (!X509_set_subject_name(certificate.get(), x509_subject->get() /* copied */)) {
257 return CertUtilsError::BoringSsl;
258 }
259 } else {
260 return std::get<CertUtilsError>(subjectName);
261 }
262
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800263 time_t notBeforeTime = saturate<time_t>(activeDateTimeMilliSeconds / 1000);
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800264 // Set activation date.
265 ASN1_TIME_Ptr notBefore(ASN1_TIME_new());
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800266 if (!notBefore || !ASN1_TIME_set(notBefore.get(), notBeforeTime) ||
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800267 !X509_set_notBefore(certificate.get(), notBefore.get() /* Don't release; copied */))
268 return CertUtilsError::BoringSsl;
269
270 // Set expiration date.
271 time_t notAfterTime;
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800272 notAfterTime = saturate<time_t>(usageExpireDateTimeMilliSeconds / 1000);
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800273
274 ASN1_TIME_Ptr notAfter(ASN1_TIME_new());
275 if (!notAfter || !ASN1_TIME_set(notAfter.get(), notAfterTime) ||
276 !X509_set_notAfter(certificate.get(), notAfter.get() /* Don't release; copied */)) {
277 return CertUtilsError::BoringSsl;
278 }
279
280 return certificate;
281}
282
283std::variant<CertUtilsError, X509_Ptr>
Janis Danisevskis2c084012021-01-31 22:23:17 -0800284makeCert(const EVP_PKEY* evp_pkey,
285 std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,
286 std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800287 const int64_t activeDateTimeMilliSeconds, const int64_t usageExpireDateTimeMilliSeconds,
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800288 bool addSubjectKeyIdEx, std::optional<KeyUsageExtension> keyUsageEx,
289 std::optional<BasicConstraintsExtension> basicConstraints) {
290
291 // Make the rump certificate with serial, subject, not before and not after dates.
292 auto certificateV =
293 makeCertRump(serial, subject, activeDateTimeMilliSeconds, usageExpireDateTimeMilliSeconds);
294 if (auto error = std::get_if<CertUtilsError>(&certificateV)) {
295 return *error;
296 }
297 auto certificate = std::move(std::get<X509_Ptr>(certificateV));
298
299 // Set the public key.
300 if (!X509_set_pubkey(certificate.get(), const_cast<EVP_PKEY*>(evp_pkey))) {
301 return CertUtilsError::BoringSsl;
302 }
303
304 if (keyUsageEx) {
305 // Make and add the key usage extension.
306 auto key_usage_extensionV = makeKeyUsageExtension(
307 keyUsageEx->isSigningKey, keyUsageEx->isEncryptionKey, keyUsageEx->isCertificationKey);
308 if (auto error = std::get_if<CertUtilsError>(&key_usage_extensionV)) {
309 return *error;
310 }
311 auto key_usage_extension = std::move(std::get<ASN1_BIT_STRING_Ptr>(key_usage_extensionV));
312 if (!X509_add1_ext_i2d(certificate.get(), NID_key_usage,
313 key_usage_extension.get() /* Don't release; copied */,
314 true /* critical */, 0 /* flags */)) {
315 return CertUtilsError::BoringSsl;
316 }
317 }
318
319 if (basicConstraints) {
320 // Make and add basic constraints
321 auto basic_constraints_extensionV =
322 makeBasicConstraintsExtension(basicConstraints->isCa, basicConstraints->pathLength);
323 if (auto error = std::get_if<CertUtilsError>(&basic_constraints_extensionV)) {
324 return *error;
325 }
326 auto basic_constraints_extension =
327 std::move(std::get<BASIC_CONSTRAINTS_Ptr>(basic_constraints_extensionV));
328 if (!X509_add1_ext_i2d(certificate.get(), NID_basic_constraints,
329 basic_constraints_extension.get() /* Don't release; copied */,
330 true /* critical */, 0 /* flags */)) {
331 return CertUtilsError::BoringSsl;
332 }
333 }
334
335 if (addSubjectKeyIdEx) {
336 // Make and add subject key id extension.
337 auto keyidV = makeKeyId(certificate.get());
338 if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
339 return *error;
340 }
341 auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
342
343 auto subject_key_extensionV = makeSubjectKeyExtension(keyid);
344 if (auto error = std::get_if<CertUtilsError>(&subject_key_extensionV)) {
345 return *error;
346 }
347 auto subject_key_extension =
348 std::move(std::get<ASN1_OCTET_STRING_Ptr>(subject_key_extensionV));
349 if (!X509_add1_ext_i2d(certificate.get(), NID_subject_key_identifier,
350 subject_key_extension.get() /* Don't release; copied */,
351 false /* critical */, 0 /* flags */)) {
352 return CertUtilsError::BoringSsl;
353 }
354 }
355
356 return certificate;
357}
358
359CertUtilsError setIssuer(X509* cert, const X509* signingCert, bool addAuthKeyExt) {
360
361 X509_NAME* issuerName(X509_get_subject_name(signingCert));
362
363 // Set Issuer Name
364 if (issuerName) {
365 if (!X509_set_issuer_name(cert, issuerName /* copied */)) {
366 return CertUtilsError::BoringSsl;
367 }
368 } else {
369 return CertUtilsError::Encoding;
370 }
371
372 if (addAuthKeyExt) {
373 // Make and add authority key extension - self signed.
374 auto keyidV = makeKeyId(signingCert);
375 if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
376 return *error;
377 }
378 auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
379
380 auto auth_key_extensionV = makeAuthorityKeyExtension(keyid);
381 if (auto error = std::get_if<CertUtilsError>(&auth_key_extensionV)) {
382 return *error;
383 }
384 auto auth_key_extension = std::move(std::get<AUTHORITY_KEYID_Ptr>(auth_key_extensionV));
385 if (!X509_add1_ext_i2d(cert, NID_authority_key_identifier, auth_key_extension.get(), false,
386 0)) {
387 return CertUtilsError::BoringSsl;
388 }
389 }
390 return CertUtilsError::Ok;
391}
392
393// Takes a certificate a signing certificate and the raw private signing_key. And signs
394// the certificate with the latter.
395CertUtilsError signCert(X509* certificate, EVP_PKEY* signing_key) {
396
397 if (certificate == nullptr) {
398 return CertUtilsError::UnexpectedNullPointer;
399 }
400
401 if (!X509_sign(certificate, signing_key, EVP_sha256())) {
402 return CertUtilsError::BoringSsl;
403 }
404
405 return CertUtilsError::Ok;
406}
407
408std::variant<CertUtilsError, std::vector<uint8_t>> encodeCert(X509* certificate) {
409 int len = i2d_X509(certificate, nullptr);
410 if (len < 0) {
411 return CertUtilsError::BoringSsl;
412 }
413
414 auto result = std::vector<uint8_t>(len);
415 uint8_t* p = result.data();
416
417 if (i2d_X509(certificate, &p) < 0) {
418 return CertUtilsError::BoringSsl;
419 }
420 return result;
421}
422
423CertUtilsError setRsaDigestAlgorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
424 if (alg_ptr == nullptr || digest == nullptr) {
425 return CertUtilsError::UnexpectedNullPointer;
426 }
427 *alg_ptr = X509_ALGOR_new();
428 if (*alg_ptr == nullptr) {
429 return CertUtilsError::MemoryAllocation;
430 }
431 X509_ALGOR_set_md(*alg_ptr, digest);
432 return CertUtilsError::Ok;
433}
434
435CertUtilsError setPssMaskGeneratorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
436 X509_ALGOR* mgf1_digest = nullptr;
437 if (auto error = setRsaDigestAlgorField(&mgf1_digest, digest)) {
438 return error;
439 }
440 X509_ALGOR_Ptr mgf1_digest_ptr(mgf1_digest);
441
442 ASN1_OCTET_STRING* mgf1_digest_algor_str = nullptr;
443 if (!ASN1_item_pack(mgf1_digest, ASN1_ITEM_rptr(X509_ALGOR), &mgf1_digest_algor_str)) {
444 return CertUtilsError::Encoding;
445 }
446 ASN1_OCTET_STRING_Ptr mgf1_digest_algor_str_ptr(mgf1_digest_algor_str);
447
448 *alg_ptr = X509_ALGOR_new();
449 if (*alg_ptr == nullptr) {
450 return CertUtilsError::MemoryAllocation;
451 }
452 X509_ALGOR_set0(*alg_ptr, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, mgf1_digest_algor_str);
453 // *alg_ptr took ownership of the octet string
454 mgf1_digest_algor_str_ptr.release();
455 return CertUtilsError::Ok;
456}
457
458static CertUtilsError setSaltLength(RSA_PSS_PARAMS* pss_params, unsigned length) {
459 pss_params->saltLength = ASN1_INTEGER_new();
460 if (pss_params->saltLength == nullptr) {
461 return CertUtilsError::MemoryAllocation;
462 }
463 if (!ASN1_INTEGER_set(pss_params->saltLength, length)) {
464 return CertUtilsError::Encoding;
465 };
466 return CertUtilsError::Ok;
467}
468
469std::variant<CertUtilsError, ASN1_STRING_Ptr> buildRsaPssParameter(Digest digest) {
470 RSA_PSS_PARAMS_Ptr pss(RSA_PSS_PARAMS_new());
471 if (!pss) {
472 return CertUtilsError::MemoryAllocation;
473 }
474
475 const EVP_MD* md = nullptr;
476
477 switch (digest) {
478 case Digest::SHA1:
479 break;
480 case Digest::SHA224:
481 md = EVP_sha224();
482 break;
483 case Digest::SHA256:
484 md = EVP_sha256();
485 break;
486 case Digest::SHA384:
487 md = EVP_sha384();
488 break;
489 case Digest::SHA512:
490 md = EVP_sha512();
491 break;
492 default:
493 return CertUtilsError::InvalidArgument;
494 }
495
496 if (md != nullptr) {
497 if (auto error = setSaltLength(pss.get(), EVP_MD_size(md))) {
498 return error;
499 }
500 if (auto error = setRsaDigestAlgorField(&pss->hashAlgorithm, md)) {
501 return error;
502 }
503 if (auto error = setPssMaskGeneratorField(&pss->maskGenAlgorithm, md)) {
504 return error;
505 }
506 }
507
508 ASN1_STRING* algo_str = nullptr;
509 if (!ASN1_item_pack(pss.get(), ASN1_ITEM_rptr(RSA_PSS_PARAMS), &algo_str)) {
510 return CertUtilsError::BoringSsl;
511 }
512
513 return ASN1_STRING_Ptr(algo_str);
514}
515
David Benjamin891b9542021-05-06 13:36:46 -0400516std::variant<CertUtilsError, X509_ALGOR_Ptr> makeAlgo(Algo algo, Padding padding, Digest digest) {
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800517 ASN1_STRING_Ptr param;
518 int param_type = V_ASN1_UNDEF;
519 int nid = 0;
520 switch (algo) {
521 case Algo::ECDSA:
522 switch (digest) {
523 case Digest::SHA1:
524 nid = NID_ecdsa_with_SHA1;
525 break;
526 case Digest::SHA224:
527 nid = NID_ecdsa_with_SHA224;
528 break;
529 case Digest::SHA256:
530 nid = NID_ecdsa_with_SHA256;
531 break;
532 case Digest::SHA384:
533 nid = NID_ecdsa_with_SHA384;
534 break;
535 case Digest::SHA512:
536 nid = NID_ecdsa_with_SHA512;
537 break;
538 default:
539 return CertUtilsError::InvalidArgument;
540 }
541 break;
542 case Algo::RSA:
543 switch (padding) {
544 case Padding::PKCS1_5:
545 param_type = V_ASN1_NULL;
546 switch (digest) {
547 case Digest::SHA1:
548 nid = NID_sha1WithRSAEncryption;
549 break;
550 case Digest::SHA224:
551 nid = NID_sha224WithRSAEncryption;
552 break;
553 case Digest::SHA256:
554 nid = NID_sha256WithRSAEncryption;
555 break;
556 case Digest::SHA384:
557 nid = NID_sha384WithRSAEncryption;
558 break;
559 case Digest::SHA512:
560 nid = NID_sha512WithRSAEncryption;
561 break;
562 default:
563 return CertUtilsError::InvalidArgument;
564 }
565 break;
566 case Padding::PSS: {
567 auto v = buildRsaPssParameter(digest);
568 if (auto param_str = std::get_if<ASN1_STRING_Ptr>(&v)) {
569 param = std::move(*param_str);
570 param_type = V_ASN1_SEQUENCE;
571 nid = NID_rsassaPss;
572 } else {
573 return std::get<CertUtilsError>(v);
574 }
575 break;
576 }
577 default:
578 return CertUtilsError::InvalidArgument;
579 }
580 break;
581 default:
582 return CertUtilsError::InvalidArgument;
583 }
584
David Benjamin891b9542021-05-06 13:36:46 -0400585 X509_ALGOR_Ptr result(X509_ALGOR_new());
586 if (!result) {
587 return CertUtilsError::MemoryAllocation;
588 }
589 if (!X509_ALGOR_set0(result.get(), OBJ_nid2obj(nid), param_type, param.get())) {
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800590 return CertUtilsError::Encoding;
591 }
592 // The X509 struct took ownership.
593 param.release();
David Benjamin891b9542021-05-06 13:36:46 -0400594 return result;
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800595}
596
597// This function allows for signing a
598CertUtilsError signCertWith(X509* certificate,
599 std::function<std::vector<uint8_t>(const uint8_t*, size_t)> sign,
600 Algo algo, Padding padding, Digest digest) {
David Benjamin891b9542021-05-06 13:36:46 -0400601 auto algo_objV = makeAlgo(algo, padding, digest);
602 if (auto error = std::get_if<CertUtilsError>(&algo_objV)) {
603 return *error;
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800604 }
David Benjamin891b9542021-05-06 13:36:46 -0400605 auto& algo_obj = std::get<X509_ALGOR_Ptr>(algo_objV);
606 if (!X509_set1_signature_algo(certificate, algo_obj.get())) {
607 return CertUtilsError::BoringSsl;
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800608 }
609
610 uint8_t* cert_buf = nullptr;
Greg Kaiser9b9704f2020-11-19 16:24:30 -0800611 int buf_len = i2d_re_X509_tbs(certificate, &cert_buf);
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800612 if (buf_len < 0) {
613 return CertUtilsError::Encoding;
614 }
615
616 bssl::UniquePtr<uint8_t> free_cert_buf(cert_buf);
617 auto signature = sign(cert_buf, buf_len);
Janis Danisevskisdc502d12021-01-15 08:52:12 -0800618 if (signature.empty()) {
619 return CertUtilsError::SignatureFailed;
620 }
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800621
David Benjamin891b9542021-05-06 13:36:46 -0400622 if (!X509_set1_signature_value(certificate, signature.data(), signature.size())) {
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800623 return CertUtilsError::BoringSsl;
624 }
625
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800626 return CertUtilsError::Ok;
627}
628
629} // namespace keystore