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