blob: 31c7fb41a61b4ec882f5ce5d5ab68e1f13c49646 [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
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800170template <typename Out, typename In> static Out saturate(In in) {
171 if constexpr (std::is_signed_v<Out> == std::is_signed_v<In>) {
172 if constexpr (sizeof(Out) >= sizeof(In)) {
173 // Same sign, and In fits into Out. Cast is lossless.
174 return static_cast<Out>(in);
175 } else {
176 // Out is smaller than In we may need to truncate.
177 // We pick the smaller of `out::max()` and the greater of `out::min()` and `in`.
178 return static_cast<Out>(
179 std::min(static_cast<In>(std::numeric_limits<Out>::max()),
180 std::max(static_cast<In>(std::numeric_limits<Out>::min()), in)));
181 }
182 } else {
183 // So we have different signs. This puts the lower bound at 0 because either input or output
184 // is unsigned. The upper bound is max of the smaller type or, if they are equal the max of
185 // the signed type.
186 if constexpr (std::is_signed_v<Out>) {
187 if constexpr (sizeof(Out) > sizeof(In)) {
188 return static_cast<Out>(in);
189 } else {
190 // Because `out` is the signed one, the lower bound of `in` is 0 and fits into
191 // `out`. We just have to compare the maximum and we do it in type In because it has
192 // a greater range than Out, so Out::max() is guaranteed to fit.
193 return static_cast<Out>(
194 std::min(static_cast<In>(std::numeric_limits<Out>::max()), in));
195 }
196 } else {
197 // Out is unsigned. So we can return 0 if in is negative.
198 if (in < 0) return 0;
199 if constexpr (sizeof(Out) >= sizeof(In)) {
200 // If Out is wider or equal we can assign lossless.
201 return static_cast<Out>(in);
202 } else {
203 // Otherwise we have to take the minimum of Out::max() and `in`.
204 return static_cast<Out>(
205 std::min(static_cast<In>(std::numeric_limits<Out>::max()), in));
206 }
207 }
208 }
209}
210
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800211// 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.
215std::variant<CertUtilsError, X509_Ptr>
Janis Danisevskis2c084012021-01-31 22:23:17 -0800216makeCertRump(std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,
217 std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800218 const int64_t activeDateTimeMilliSeconds,
219 const int64_t usageExpireDateTimeMilliSeconds) {
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800220
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800221 // 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
Janis Danisevskis2c084012021-01-31 22:23:17 -0800232 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
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800246 // Set the certificate serialNumber
247 ASN1_INTEGER_Ptr serialNumber(ASN1_INTEGER_new());
Janis Danisevskis2c084012021-01-31 22:23:17 -0800248 if (!serialNumber || !BN_to_ASN1_INTEGER(bn_serial.get(), serialNumber.get()) ||
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800249 !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
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800262 time_t notBeforeTime = saturate<time_t>(activeDateTimeMilliSeconds / 1000);
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800263 // Set activation date.
264 ASN1_TIME_Ptr notBefore(ASN1_TIME_new());
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800265 if (!notBefore || !ASN1_TIME_set(notBefore.get(), notBeforeTime) ||
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800266 !X509_set_notBefore(certificate.get(), notBefore.get() /* Don't release; copied */))
267 return CertUtilsError::BoringSsl;
268
269 // Set expiration date.
270 time_t notAfterTime;
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800271 notAfterTime = saturate<time_t>(usageExpireDateTimeMilliSeconds / 1000);
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800272
273 ASN1_TIME_Ptr notAfter(ASN1_TIME_new());
274 if (!notAfter || !ASN1_TIME_set(notAfter.get(), notAfterTime) ||
275 !X509_set_notAfter(certificate.get(), notAfter.get() /* Don't release; copied */)) {
276 return CertUtilsError::BoringSsl;
277 }
278
279 return certificate;
280}
281
282std::variant<CertUtilsError, X509_Ptr>
Janis Danisevskis2c084012021-01-31 22:23:17 -0800283makeCert(const EVP_PKEY* evp_pkey,
284 std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,
285 std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,
Janis Danisevskis3793a5e2021-01-31 13:04:01 -0800286 const int64_t activeDateTimeMilliSeconds, const int64_t usageExpireDateTimeMilliSeconds,
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800287 bool addSubjectKeyIdEx, std::optional<KeyUsageExtension> keyUsageEx,
288 std::optional<BasicConstraintsExtension> basicConstraints) {
289
290 // Make the rump certificate with serial, subject, not before and not after dates.
291 auto certificateV =
292 makeCertRump(serial, subject, activeDateTimeMilliSeconds, usageExpireDateTimeMilliSeconds);
293 if (auto error = std::get_if<CertUtilsError>(&certificateV)) {
294 return *error;
295 }
296 auto certificate = std::move(std::get<X509_Ptr>(certificateV));
297
298 // Set the public key.
299 if (!X509_set_pubkey(certificate.get(), const_cast<EVP_PKEY*>(evp_pkey))) {
300 return CertUtilsError::BoringSsl;
301 }
302
303 if (keyUsageEx) {
304 // Make and add the key usage extension.
305 auto key_usage_extensionV = makeKeyUsageExtension(
306 keyUsageEx->isSigningKey, keyUsageEx->isEncryptionKey, keyUsageEx->isCertificationKey);
307 if (auto error = std::get_if<CertUtilsError>(&key_usage_extensionV)) {
308 return *error;
309 }
310 auto key_usage_extension = std::move(std::get<ASN1_BIT_STRING_Ptr>(key_usage_extensionV));
311 if (!X509_add1_ext_i2d(certificate.get(), NID_key_usage,
312 key_usage_extension.get() /* Don't release; copied */,
313 true /* critical */, 0 /* flags */)) {
314 return CertUtilsError::BoringSsl;
315 }
316 }
317
318 if (basicConstraints) {
319 // Make and add basic constraints
320 auto basic_constraints_extensionV =
321 makeBasicConstraintsExtension(basicConstraints->isCa, basicConstraints->pathLength);
322 if (auto error = std::get_if<CertUtilsError>(&basic_constraints_extensionV)) {
323 return *error;
324 }
325 auto basic_constraints_extension =
326 std::move(std::get<BASIC_CONSTRAINTS_Ptr>(basic_constraints_extensionV));
327 if (!X509_add1_ext_i2d(certificate.get(), NID_basic_constraints,
328 basic_constraints_extension.get() /* Don't release; copied */,
329 true /* critical */, 0 /* flags */)) {
330 return CertUtilsError::BoringSsl;
331 }
332 }
333
334 if (addSubjectKeyIdEx) {
335 // Make and add subject key id extension.
336 auto keyidV = makeKeyId(certificate.get());
337 if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
338 return *error;
339 }
340 auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
341
342 auto subject_key_extensionV = makeSubjectKeyExtension(keyid);
343 if (auto error = std::get_if<CertUtilsError>(&subject_key_extensionV)) {
344 return *error;
345 }
346 auto subject_key_extension =
347 std::move(std::get<ASN1_OCTET_STRING_Ptr>(subject_key_extensionV));
348 if (!X509_add1_ext_i2d(certificate.get(), NID_subject_key_identifier,
349 subject_key_extension.get() /* Don't release; copied */,
350 false /* critical */, 0 /* flags */)) {
351 return CertUtilsError::BoringSsl;
352 }
353 }
354
355 return certificate;
356}
357
358CertUtilsError setIssuer(X509* cert, const X509* signingCert, bool addAuthKeyExt) {
359
360 X509_NAME* issuerName(X509_get_subject_name(signingCert));
361
362 // Set Issuer Name
363 if (issuerName) {
364 if (!X509_set_issuer_name(cert, issuerName /* copied */)) {
365 return CertUtilsError::BoringSsl;
366 }
367 } else {
368 return CertUtilsError::Encoding;
369 }
370
371 if (addAuthKeyExt) {
372 // Make and add authority key extension - self signed.
373 auto keyidV = makeKeyId(signingCert);
374 if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
375 return *error;
376 }
377 auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
378
379 auto auth_key_extensionV = makeAuthorityKeyExtension(keyid);
380 if (auto error = std::get_if<CertUtilsError>(&auth_key_extensionV)) {
381 return *error;
382 }
383 auto auth_key_extension = std::move(std::get<AUTHORITY_KEYID_Ptr>(auth_key_extensionV));
384 if (!X509_add1_ext_i2d(cert, NID_authority_key_identifier, auth_key_extension.get(), false,
385 0)) {
386 return CertUtilsError::BoringSsl;
387 }
388 }
389 return CertUtilsError::Ok;
390}
391
392// Takes a certificate a signing certificate and the raw private signing_key. And signs
393// the certificate with the latter.
394CertUtilsError signCert(X509* certificate, EVP_PKEY* signing_key) {
395
396 if (certificate == nullptr) {
397 return CertUtilsError::UnexpectedNullPointer;
398 }
399
400 if (!X509_sign(certificate, signing_key, EVP_sha256())) {
401 return CertUtilsError::BoringSsl;
402 }
403
404 return CertUtilsError::Ok;
405}
406
407std::variant<CertUtilsError, std::vector<uint8_t>> encodeCert(X509* certificate) {
408 int len = i2d_X509(certificate, nullptr);
409 if (len < 0) {
410 return CertUtilsError::BoringSsl;
411 }
412
413 auto result = std::vector<uint8_t>(len);
414 uint8_t* p = result.data();
415
416 if (i2d_X509(certificate, &p) < 0) {
417 return CertUtilsError::BoringSsl;
418 }
419 return result;
420}
421
422CertUtilsError setRsaDigestAlgorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
423 if (alg_ptr == nullptr || digest == nullptr) {
424 return CertUtilsError::UnexpectedNullPointer;
425 }
426 *alg_ptr = X509_ALGOR_new();
427 if (*alg_ptr == nullptr) {
428 return CertUtilsError::MemoryAllocation;
429 }
430 X509_ALGOR_set_md(*alg_ptr, digest);
431 return CertUtilsError::Ok;
432}
433
434CertUtilsError setPssMaskGeneratorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
435 X509_ALGOR* mgf1_digest = nullptr;
436 if (auto error = setRsaDigestAlgorField(&mgf1_digest, digest)) {
437 return error;
438 }
439 X509_ALGOR_Ptr mgf1_digest_ptr(mgf1_digest);
440
441 ASN1_OCTET_STRING* mgf1_digest_algor_str = nullptr;
442 if (!ASN1_item_pack(mgf1_digest, ASN1_ITEM_rptr(X509_ALGOR), &mgf1_digest_algor_str)) {
443 return CertUtilsError::Encoding;
444 }
445 ASN1_OCTET_STRING_Ptr mgf1_digest_algor_str_ptr(mgf1_digest_algor_str);
446
447 *alg_ptr = X509_ALGOR_new();
448 if (*alg_ptr == nullptr) {
449 return CertUtilsError::MemoryAllocation;
450 }
451 X509_ALGOR_set0(*alg_ptr, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, mgf1_digest_algor_str);
452 // *alg_ptr took ownership of the octet string
453 mgf1_digest_algor_str_ptr.release();
454 return CertUtilsError::Ok;
455}
456
457static CertUtilsError setSaltLength(RSA_PSS_PARAMS* pss_params, unsigned length) {
458 pss_params->saltLength = ASN1_INTEGER_new();
459 if (pss_params->saltLength == nullptr) {
460 return CertUtilsError::MemoryAllocation;
461 }
462 if (!ASN1_INTEGER_set(pss_params->saltLength, length)) {
463 return CertUtilsError::Encoding;
464 };
465 return CertUtilsError::Ok;
466}
467
468std::variant<CertUtilsError, ASN1_STRING_Ptr> buildRsaPssParameter(Digest digest) {
469 RSA_PSS_PARAMS_Ptr pss(RSA_PSS_PARAMS_new());
470 if (!pss) {
471 return CertUtilsError::MemoryAllocation;
472 }
473
474 const EVP_MD* md = nullptr;
475
476 switch (digest) {
477 case Digest::SHA1:
478 break;
479 case Digest::SHA224:
480 md = EVP_sha224();
481 break;
482 case Digest::SHA256:
483 md = EVP_sha256();
484 break;
485 case Digest::SHA384:
486 md = EVP_sha384();
487 break;
488 case Digest::SHA512:
489 md = EVP_sha512();
490 break;
491 default:
492 return CertUtilsError::InvalidArgument;
493 }
494
495 if (md != nullptr) {
496 if (auto error = setSaltLength(pss.get(), EVP_MD_size(md))) {
497 return error;
498 }
499 if (auto error = setRsaDigestAlgorField(&pss->hashAlgorithm, md)) {
500 return error;
501 }
502 if (auto error = setPssMaskGeneratorField(&pss->maskGenAlgorithm, md)) {
503 return error;
504 }
505 }
506
507 ASN1_STRING* algo_str = nullptr;
508 if (!ASN1_item_pack(pss.get(), ASN1_ITEM_rptr(RSA_PSS_PARAMS), &algo_str)) {
509 return CertUtilsError::BoringSsl;
510 }
511
512 return ASN1_STRING_Ptr(algo_str);
513}
514
515CertUtilsError makeAndSetAlgo(X509_ALGOR* algo_field, Algo algo, Padding padding, Digest digest) {
516 if (algo_field == nullptr) {
517 return CertUtilsError::UnexpectedNullPointer;
518 }
519 ASN1_STRING_Ptr param;
520 int param_type = V_ASN1_UNDEF;
521 int nid = 0;
522 switch (algo) {
523 case Algo::ECDSA:
524 switch (digest) {
525 case Digest::SHA1:
526 nid = NID_ecdsa_with_SHA1;
527 break;
528 case Digest::SHA224:
529 nid = NID_ecdsa_with_SHA224;
530 break;
531 case Digest::SHA256:
532 nid = NID_ecdsa_with_SHA256;
533 break;
534 case Digest::SHA384:
535 nid = NID_ecdsa_with_SHA384;
536 break;
537 case Digest::SHA512:
538 nid = NID_ecdsa_with_SHA512;
539 break;
540 default:
541 return CertUtilsError::InvalidArgument;
542 }
543 break;
544 case Algo::RSA:
545 switch (padding) {
546 case Padding::PKCS1_5:
547 param_type = V_ASN1_NULL;
548 switch (digest) {
549 case Digest::SHA1:
550 nid = NID_sha1WithRSAEncryption;
551 break;
552 case Digest::SHA224:
553 nid = NID_sha224WithRSAEncryption;
554 break;
555 case Digest::SHA256:
556 nid = NID_sha256WithRSAEncryption;
557 break;
558 case Digest::SHA384:
559 nid = NID_sha384WithRSAEncryption;
560 break;
561 case Digest::SHA512:
562 nid = NID_sha512WithRSAEncryption;
563 break;
564 default:
565 return CertUtilsError::InvalidArgument;
566 }
567 break;
568 case Padding::PSS: {
569 auto v = buildRsaPssParameter(digest);
570 if (auto param_str = std::get_if<ASN1_STRING_Ptr>(&v)) {
571 param = std::move(*param_str);
572 param_type = V_ASN1_SEQUENCE;
573 nid = NID_rsassaPss;
574 } else {
575 return std::get<CertUtilsError>(v);
576 }
577 break;
578 }
579 default:
580 return CertUtilsError::InvalidArgument;
581 }
582 break;
583 default:
584 return CertUtilsError::InvalidArgument;
585 }
586
587 if (!X509_ALGOR_set0(algo_field, OBJ_nid2obj(nid), param_type, param.get())) {
588 return CertUtilsError::Encoding;
589 }
590 // The X509 struct took ownership.
591 param.release();
592 return CertUtilsError::Ok;
593}
594
595// This function allows for signing a
596CertUtilsError signCertWith(X509* certificate,
597 std::function<std::vector<uint8_t>(const uint8_t*, size_t)> sign,
598 Algo algo, Padding padding, Digest digest) {
599 if (auto error = makeAndSetAlgo(certificate->sig_alg, algo, padding, digest)) {
600 return error;
601 }
602 if (auto error = makeAndSetAlgo(certificate->cert_info->signature, algo, padding, digest)) {
603 return error;
604 }
605
606 uint8_t* cert_buf = nullptr;
Greg Kaiser9b9704f2020-11-19 16:24:30 -0800607 int buf_len = i2d_re_X509_tbs(certificate, &cert_buf);
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800608 if (buf_len < 0) {
609 return CertUtilsError::Encoding;
610 }
611
612 bssl::UniquePtr<uint8_t> free_cert_buf(cert_buf);
613 auto signature = sign(cert_buf, buf_len);
Janis Danisevskisdc502d12021-01-15 08:52:12 -0800614 if (signature.empty()) {
615 return CertUtilsError::SignatureFailed;
616 }
Janis Danisevskisa7c72db2020-11-05 12:02:22 -0800617
618 if (!ASN1_STRING_set(certificate->signature, signature.data(), signature.size())) {
619 return CertUtilsError::BoringSsl;
620 }
621
622 certificate->signature->flags &= ~(0x07);
623 certificate->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
624
625 return CertUtilsError::Ok;
626}
627
628} // namespace keystore