blob: d67bea6c19e372851f47c05b52eabc42247cb11f [file] [log] [blame]
Martijn Coenen95194842020-09-24 16:56:46 +02001/*
2 * Copyright (C) 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
Alan Stokesb1821782021-06-07 14:57:15 +010017#include "CertUtils.h"
18
Martijn Coenen95194842020-09-24 16:56:46 +020019#include <android-base/logging.h>
20#include <android-base/result.h>
21
22#include <openssl/bn.h>
23#include <openssl/crypto.h>
24#include <openssl/pkcs7.h>
25#include <openssl/rsa.h>
David Benjamin891b9542021-05-06 13:36:46 -040026#include <openssl/x509.h>
Martijn Coenen95194842020-09-24 16:56:46 +020027#include <openssl/x509v3.h>
28
Alan Stokesbfd2ec02021-06-09 18:00:54 +010029#include <optional>
Martijn Coenen95194842020-09-24 16:56:46 +020030#include <vector>
Martijn Coenenba1c9dc2021-02-04 13:18:29 +010031
32#include "KeyConstants.h"
33
Alan Stokes35049b62021-06-25 12:16:13 +010034// Common properties for all of our certificates.
Martijn Coenen95194842020-09-24 16:56:46 +020035constexpr int kCertLifetimeSeconds = 10 * 365 * 24 * 60 * 60;
Alan Stokes35049b62021-06-25 12:16:13 +010036const char* const kIssuerCountry = "US";
37const char* const kIssuerOrg = "Android";
Martijn Coenen95194842020-09-24 16:56:46 +020038
Alan Stokesbfd2ec02021-06-09 18:00:54 +010039using android::base::ErrnoError;
Martijn Coenen95194842020-09-24 16:56:46 +020040using android::base::Error;
Alan Stokesbfd2ec02021-06-09 18:00:54 +010041using android::base::Result;
Martijn Coenen95194842020-09-24 16:56:46 +020042
Alan Stokesbfd2ec02021-06-09 18:00:54 +010043static Result<bssl::UniquePtr<X509>> loadX509(const std::string& path) {
44 X509* rawCert;
45 auto f = fopen(path.c_str(), "re");
46 if (f == nullptr) {
47 return Error() << "Failed to open " << path;
48 }
49 if (!d2i_X509_fp(f, &rawCert)) {
50 fclose(f);
51 return Error() << "Unable to decode x509 cert at " << path;
52 }
53 bssl::UniquePtr<X509> cert(rawCert);
Martijn Coenen95194842020-09-24 16:56:46 +020054
Alan Stokesbfd2ec02021-06-09 18:00:54 +010055 fclose(f);
56 return cert;
57}
Martijn Coenen95194842020-09-24 16:56:46 +020058
Alan Stokesbfd2ec02021-06-09 18:00:54 +010059static X509V3_CTX makeContext(X509* issuer, X509* subject) {
60 X509V3_CTX context = {};
61 X509V3_set_ctx(&context, issuer, subject, nullptr, nullptr, 0);
62 return context;
63}
64
65static bool add_ext(X509V3_CTX* context, X509* cert, int nid, const char* value) {
66 bssl::UniquePtr<X509_EXTENSION> ex(X509V3_EXT_nconf_nid(nullptr, context, nid, value));
Martijn Coenen95194842020-09-24 16:56:46 +020067 if (!ex) {
68 return false;
69 }
70
Alan Stokesbfd2ec02021-06-09 18:00:54 +010071 X509_add_ext(cert, ex.get(), -1);
Martijn Coenen95194842020-09-24 16:56:46 +020072 return true;
73}
74
Alan Stokesbfd2ec02021-06-09 18:00:54 +010075static void addNameEntry(X509_NAME* name, const char* field, const char* value) {
76 X509_NAME_add_entry_by_txt(name, field, MBSTRING_ASC,
77 reinterpret_cast<const unsigned char*>(value), -1, -1, 0);
78}
79
Alan Stokes8b4cb962021-07-06 17:45:39 +010080static Result<bssl::UniquePtr<RSA>> getRsaFromModulus(const std::vector<uint8_t>& publicKey) {
David Benjamin891b9542021-05-06 13:36:46 -040081 bssl::UniquePtr<BIGNUM> n(BN_new());
82 bssl::UniquePtr<BIGNUM> e(BN_new());
Martijn Coenendc05bb32021-03-08 10:52:48 +010083 bssl::UniquePtr<RSA> rsaPubkey(RSA_new());
David Benjamin891b9542021-05-06 13:36:46 -040084 if (!n || !e || !rsaPubkey || !BN_bin2bn(publicKey.data(), publicKey.size(), n.get()) ||
85 !BN_set_word(e.get(), kRsaKeyExponent) ||
86 !RSA_set0_key(rsaPubkey.get(), n.get(), e.get(), /*d=*/nullptr)) {
87 return Error() << "Failed to create RSA key";
88 }
89 // RSA_set0_key takes ownership of |n| and |e| on success.
90 (void)n.release();
91 (void)e.release();
Martijn Coenendc05bb32021-03-08 10:52:48 +010092
93 return rsaPubkey;
94}
95
Alan Stokes8b4cb962021-07-06 17:45:39 +010096static Result<bssl::UniquePtr<RSA>>
97getRsaFromRsaPublicKey(const std::vector<uint8_t>& rsaPublicKey) {
98 auto derBytes = rsaPublicKey.data();
99 bssl::UniquePtr<RSA> rsaKey(d2i_RSAPublicKey(nullptr, &derBytes, rsaPublicKey.size()));
100 if (rsaKey.get() == nullptr) {
101 return Error() << "Failed to parse RsaPublicKey";
102 }
103 if (derBytes != rsaPublicKey.data() + rsaPublicKey.size()) {
104 return Error() << "Key has unexpected trailing data";
105 }
106
107 return rsaKey;
108}
109
110static Result<bssl::UniquePtr<EVP_PKEY>> modulusToRsaPkey(const std::vector<uint8_t>& publicKey) {
111 // "publicKey" corresponds to the raw public key bytes - need to create
112 // a new RSA key with the correct exponent.
113 auto rsaPubkey = getRsaFromModulus(publicKey);
114 if (!rsaPubkey.ok()) {
115 return rsaPubkey.error();
116 }
117
118 bssl::UniquePtr<EVP_PKEY> public_key(EVP_PKEY_new());
119 if (!EVP_PKEY_assign_RSA(public_key.get(), rsaPubkey->release())) {
120 return Error() << "Failed to assign key";
121 }
122 return public_key;
123}
124
125static Result<bssl::UniquePtr<EVP_PKEY>>
126rsaPublicKeyToRsaPkey(const std::vector<uint8_t>& rsaPublicKey) {
127 // rsaPublicKey contains both modulus and exponent, DER-encoded.
128 auto rsaKey = getRsaFromRsaPublicKey(rsaPublicKey);
129 if (!rsaKey.ok()) {
130 return rsaKey.error();
131 }
132
133 bssl::UniquePtr<EVP_PKEY> public_key(EVP_PKEY_new());
134 if (!EVP_PKEY_assign_RSA(public_key.get(), rsaKey->release())) {
135 return Error() << "Failed to assign key";
136 }
137 return public_key;
138}
139
Martijn Coenendc05bb32021-03-08 10:52:48 +0100140Result<void> verifySignature(const std::string& message, const std::string& signature,
141 const std::vector<uint8_t>& publicKey) {
Alan Stokes8b4cb962021-07-06 17:45:39 +0100142 auto rsaKey = getRsaFromModulus(publicKey);
David Benjamin891b9542021-05-06 13:36:46 -0400143 if (!rsaKey.ok()) {
144 return rsaKey.error();
145 }
Martijn Coenendc05bb32021-03-08 10:52:48 +0100146 uint8_t hashBuf[SHA256_DIGEST_LENGTH];
147 SHA256(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(message.c_str())),
148 message.length(), hashBuf);
149
150 bool success = RSA_verify(NID_sha256, hashBuf, sizeof(hashBuf),
151 (const uint8_t*)signature.c_str(), signature.length(), rsaKey->get());
152
153 if (!success) {
Alan Stokes35049b62021-06-25 12:16:13 +0100154 return Error() << "Failed to verify signature";
Martijn Coenendc05bb32021-03-08 10:52:48 +0100155 }
156 return {};
157}
158
Alan Stokes8b4cb962021-07-06 17:45:39 +0100159Result<void> verifyRsaPublicKeySignature(const std::string& message, const std::string& signature,
160 const std::vector<uint8_t>& rsaPublicKey) {
161 auto rsaKey = getRsaFromRsaPublicKey(rsaPublicKey);
162 if (!rsaKey.ok()) {
163 return rsaKey.error();
Alan Stokesb1821782021-06-07 14:57:15 +0100164 }
165
Alan Stokes8b4cb962021-07-06 17:45:39 +0100166 uint8_t hashBuf[SHA256_DIGEST_LENGTH];
167 SHA256(reinterpret_cast<const uint8_t*>(message.data()), message.size(), hashBuf);
168
169 bool success = RSA_verify(NID_sha256, hashBuf, sizeof(hashBuf),
170 reinterpret_cast<const uint8_t*>(signature.data()), signature.size(),
171 rsaKey->get());
172 if (!success) {
173 return Error() << "Failed to verify signature";
Alan Stokesb1821782021-06-07 14:57:15 +0100174 }
Alan Stokes8b4cb962021-07-06 17:45:39 +0100175 return {};
Alan Stokesb1821782021-06-07 14:57:15 +0100176}
177
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100178static Result<void> createCertificate(
Alan Stokes8b4cb962021-07-06 17:45:39 +0100179 const CertSubject& subject, EVP_PKEY* publicKey,
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100180 const std::function<android::base::Result<std::string>(const std::string&)>& signFunction,
181 const std::optional<std::string>& issuerCertPath, const std::string& path) {
182
183 // If an issuer cert is specified, we are signing someone else's key.
184 // Otherwise we are signing our key - a self-signed certificate.
185 bool selfSigned = !issuerCertPath;
186
Martijn Coenen95194842020-09-24 16:56:46 +0200187 bssl::UniquePtr<X509> x509(X509_new());
188 if (!x509) {
189 return Error() << "Unable to allocate x509 container";
190 }
191 X509_set_version(x509.get(), 2);
Martijn Coenen95194842020-09-24 16:56:46 +0200192 X509_gmtime_adj(X509_get_notBefore(x509.get()), 0);
193 X509_gmtime_adj(X509_get_notAfter(x509.get()), kCertLifetimeSeconds);
Alan Stokes35049b62021-06-25 12:16:13 +0100194 ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), subject.serialNumber);
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100195
196 bssl::UniquePtr<X509_ALGOR> algor(X509_ALGOR_new());
197 if (!algor ||
198 !X509_ALGOR_set0(algor.get(), OBJ_nid2obj(NID_sha256WithRSAEncryption), V_ASN1_NULL,
199 NULL) ||
200 !X509_set1_signature_algo(x509.get(), algor.get())) {
201 return Error() << "Unable to set x509 signature algorithm";
202 }
Martijn Coenen95194842020-09-24 16:56:46 +0200203
Alan Stokes8b4cb962021-07-06 17:45:39 +0100204 if (!X509_set_pubkey(x509.get(), publicKey)) {
Martijn Coenen95194842020-09-24 16:56:46 +0200205 return Error() << "Unable to set x509 public key";
206 }
207
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100208 X509_NAME* subjectName = X509_get_subject_name(x509.get());
209 if (!subjectName) {
Martijn Coenen95194842020-09-24 16:56:46 +0200210 return Error() << "Unable to get x509 subject name";
211 }
Alan Stokes35049b62021-06-25 12:16:13 +0100212 addNameEntry(subjectName, "C", kIssuerCountry);
213 addNameEntry(subjectName, "O", kIssuerOrg);
214 addNameEntry(subjectName, "CN", subject.commonName);
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100215
216 if (selfSigned) {
217 if (!X509_set_issuer_name(x509.get(), subjectName)) {
218 return Error() << "Unable to set x509 issuer name";
219 }
220 } else {
221 X509_NAME* issuerName = X509_get_issuer_name(x509.get());
222 if (!issuerName) {
223 return Error() << "Unable to get x509 issuer name";
224 }
Alan Stokes35049b62021-06-25 12:16:13 +0100225 addNameEntry(issuerName, "C", kIssuerCountry);
226 addNameEntry(issuerName, "O", kIssuerOrg);
227 addNameEntry(issuerName, "CN", kRootSubject.commonName);
Martijn Coenen95194842020-09-24 16:56:46 +0200228 }
229
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100230 // Beware: context contains a pointer to issuerCert, so we need to keep it alive.
231 bssl::UniquePtr<X509> issuerCert;
232 X509V3_CTX context;
Martijn Coenen95194842020-09-24 16:56:46 +0200233
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100234 if (selfSigned) {
235 context = makeContext(x509.get(), x509.get());
236 } else {
237 auto certStatus = loadX509(*issuerCertPath);
238 if (!certStatus.ok()) {
239 return Error() << "Unable to load issuer cert: " << certStatus.error();
240 }
241 issuerCert = std::move(certStatus.value());
242 context = makeContext(issuerCert.get(), x509.get());
David Benjamin891b9542021-05-06 13:36:46 -0400243 }
Martijn Coenen95194842020-09-24 16:56:46 +0200244
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100245 // If it's a self-signed cert we use it for signing certs, otherwise only for signing data.
246 const char* basicConstraints = selfSigned ? "CA:TRUE" : "CA:FALSE";
247 const char* keyUsage =
248 selfSigned ? "critical,keyCertSign,cRLSign,digitalSignature" : "critical,digitalSignature";
249
250 add_ext(&context, x509.get(), NID_basic_constraints, basicConstraints);
251 add_ext(&context, x509.get(), NID_key_usage, keyUsage);
252 add_ext(&context, x509.get(), NID_subject_key_identifier, "hash");
253 add_ext(&context, x509.get(), NID_authority_key_identifier, "keyid:always");
254
Martijn Coenen95194842020-09-24 16:56:46 +0200255 // Get the data to be signed
David Benjamin891b9542021-05-06 13:36:46 -0400256 unsigned char* to_be_signed_buf(nullptr);
257 size_t to_be_signed_length = i2d_re_X509_tbs(x509.get(), &to_be_signed_buf);
Martijn Coenen95194842020-09-24 16:56:46 +0200258
David Benjamin891b9542021-05-06 13:36:46 -0400259 auto signed_data = signFunction(
260 std::string(reinterpret_cast<const char*>(to_be_signed_buf), to_be_signed_length));
Martijn Coenen95194842020-09-24 16:56:46 +0200261 if (!signed_data.ok()) {
262 return signed_data.error();
263 }
264
David Benjamin891b9542021-05-06 13:36:46 -0400265 if (!X509_set1_signature_value(x509.get(),
266 reinterpret_cast<const uint8_t*>(signed_data->data()),
267 signed_data->size())) {
268 return Error() << "Unable to set x509 signature";
269 }
Martijn Coenen95194842020-09-24 16:56:46 +0200270
Martijn Coenenc101b132021-03-18 11:23:55 +0100271 auto f = fopen(path.c_str(), "wbe");
272 if (f == nullptr) {
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100273 return ErrnoError() << "Failed to open " << path;
Martijn Coenenc101b132021-03-18 11:23:55 +0100274 }
Martijn Coenen95194842020-09-24 16:56:46 +0200275 i2d_X509_fp(f, x509.get());
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100276 if (fclose(f) != 0) {
277 return ErrnoError() << "Failed to close " << path;
278 }
Martijn Coenen95194842020-09-24 16:56:46 +0200279
280 return {};
281}
282
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100283Result<void> createSelfSignedCertificate(
284 const std::vector<uint8_t>& publicKey,
285 const std::function<Result<std::string>(const std::string&)>& signFunction,
286 const std::string& path) {
Alan Stokes8b4cb962021-07-06 17:45:39 +0100287 auto rsa_pkey = modulusToRsaPkey(publicKey);
288 if (!rsa_pkey.ok()) {
289 return rsa_pkey.error();
290 }
291
292 return createCertificate(kRootSubject, rsa_pkey.value().get(), signFunction, {}, path);
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100293}
294
295android::base::Result<void> createLeafCertificate(
Alan Stokes8b4cb962021-07-06 17:45:39 +0100296 const CertSubject& subject, const std::vector<uint8_t>& rsaPublicKey,
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100297 const std::function<android::base::Result<std::string>(const std::string&)>& signFunction,
298 const std::string& issuerCertPath, const std::string& path) {
Alan Stokes8b4cb962021-07-06 17:45:39 +0100299 auto rsa_pkey = rsaPublicKeyToRsaPkey(rsaPublicKey);
300 if (!rsa_pkey.ok()) {
301 return rsa_pkey.error();
302 }
303
304 return createCertificate(subject, rsa_pkey.value().get(), signFunction, issuerCertPath, path);
Alan Stokesbfd2ec02021-06-09 18:00:54 +0100305}
306
Martijn Coenen95194842020-09-24 16:56:46 +0200307Result<std::vector<uint8_t>> extractPublicKey(EVP_PKEY* pkey) {
308 if (pkey == nullptr) {
309 return Error() << "Failed to extract public key from x509 cert";
310 }
311
David Benjamin891b9542021-05-06 13:36:46 -0400312 if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA) {
Martijn Coenen95194842020-09-24 16:56:46 +0200313 return Error() << "The public key is not an RSA key";
314 }
315
David Benjamin891b9542021-05-06 13:36:46 -0400316 RSA* rsa = EVP_PKEY_get0_RSA(pkey);
317 auto num_bytes = BN_num_bytes(RSA_get0_n(rsa));
Martijn Coenen95194842020-09-24 16:56:46 +0200318 std::vector<uint8_t> pubKey(num_bytes);
David Benjamin891b9542021-05-06 13:36:46 -0400319 int res = BN_bn2bin(RSA_get0_n(rsa), pubKey.data());
Martijn Coenen95194842020-09-24 16:56:46 +0200320
321 if (!res) {
322 return Error() << "Failed to convert public key to bytes";
323 }
324
325 return pubKey;
326}
327
Martijn Coenenba1c9dc2021-02-04 13:18:29 +0100328Result<std::vector<uint8_t>>
329extractPublicKeyFromSubjectPublicKeyInfo(const std::vector<uint8_t>& keyData) {
Martijn Coenen95194842020-09-24 16:56:46 +0200330 auto keyDataBytes = keyData.data();
Alan Stokes3b885982021-06-07 11:34:26 +0100331 bssl::UniquePtr<EVP_PKEY> public_key(d2i_PUBKEY(nullptr, &keyDataBytes, keyData.size()));
Martijn Coenen95194842020-09-24 16:56:46 +0200332
Alan Stokes3b885982021-06-07 11:34:26 +0100333 return extractPublicKey(public_key.get());
Martijn Coenen95194842020-09-24 16:56:46 +0200334}
335
Alan Stokesb1821782021-06-07 14:57:15 +0100336Result<std::vector<uint8_t>> extractPublicKeyFromX509(const std::vector<uint8_t>& derCert) {
337 auto derCertBytes = derCert.data();
338 bssl::UniquePtr<X509> decoded_cert(d2i_X509(nullptr, &derCertBytes, derCert.size()));
Martijn Coenenba1c9dc2021-02-04 13:18:29 +0100339 if (decoded_cert.get() == nullptr) {
340 return Error() << "Failed to decode X509 certificate.";
341 }
342 bssl::UniquePtr<EVP_PKEY> decoded_pkey(X509_get_pubkey(decoded_cert.get()));
343
344 return extractPublicKey(decoded_pkey.get());
345}
346
Alan Stokesb1821782021-06-07 14:57:15 +0100347Result<std::vector<uint8_t>> extractPublicKeyFromX509(const std::string& path) {
348 auto cert = loadX509(path);
349 if (!cert.ok()) {
350 return cert.error();
351 }
352 return extractPublicKey(X509_get_pubkey(cert.value().get()));
353}
354
Alan Stokesb85739d2021-07-05 16:52:45 +0100355Result<std::vector<uint8_t>> extractRsaPublicKey(EVP_PKEY* pkey) {
356 RSA* rsa = EVP_PKEY_get0_RSA(pkey);
357 if (rsa == nullptr) {
358 return Error() << "The public key is not an RSA key";
359 }
360
361 uint8_t* out = nullptr;
362 int size = i2d_RSAPublicKey(rsa, &out);
363 if (size < 0 || !out) {
364 return Error() << "Failed to convert to RSAPublicKey";
365 }
366
367 bssl::UniquePtr<uint8_t> buffer(out);
368 std::vector<uint8_t> result(out, out + size);
369 return result;
370}
371
Alan Stokesb1821782021-06-07 14:57:15 +0100372Result<CertInfo> verifyAndExtractCertInfoFromX509(const std::string& path,
373 const std::vector<uint8_t>& publicKey) {
Alan Stokes8b4cb962021-07-06 17:45:39 +0100374 auto public_key = modulusToRsaPkey(publicKey);
Alan Stokesb1821782021-06-07 14:57:15 +0100375 if (!public_key.ok()) {
376 return public_key.error();
377 }
378
379 auto cert = loadX509(path);
380 if (!cert.ok()) {
381 return cert.error();
382 }
383 X509* x509 = cert.value().get();
384
385 // Make sure we signed it.
386 if (X509_verify(x509, public_key.value().get()) != 1) {
387 return Error() << "Failed to verify certificate.";
388 }
389
390 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509));
Alan Stokes8b4cb962021-07-06 17:45:39 +0100391 auto subject_key = extractRsaPublicKey(pkey.get());
Alan Stokesb1821782021-06-07 14:57:15 +0100392 if (!subject_key.ok()) {
393 return subject_key.error();
394 }
395
396 // The pointers here are all owned by x509, and each function handles an
397 // error return from the previous call correctly.
398 X509_NAME* name = X509_get_subject_name(x509);
399 int index = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
400 X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, index);
401 ASN1_STRING* asn1cn = X509_NAME_ENTRY_get_data(entry);
402 unsigned char* utf8cn;
403 int length = ASN1_STRING_to_UTF8(&utf8cn, asn1cn);
404 if (length < 0) {
405 return Error() << "Failed to read subject CN";
406 }
407
408 bssl::UniquePtr<unsigned char> utf8owner(utf8cn);
409 std::string cn(reinterpret_cast<char*>(utf8cn), static_cast<size_t>(length));
410
411 CertInfo cert_info{std::move(cn), std::move(subject_key.value())};
412 return cert_info;
Martijn Coenen95194842020-09-24 16:56:46 +0200413}
414
Alan Stokes35049b62021-06-25 12:16:13 +0100415Result<std::vector<uint8_t>> createPkcs7(const std::vector<uint8_t>& signed_digest,
416 const CertSubject& signer) {
Martijn Coenen95194842020-09-24 16:56:46 +0200417 CBB out, outer_seq, wrapped_seq, seq, digest_algos_set, digest_algo, null;
418 CBB content_info, issuer_and_serial, signer_infos, signer_info, sign_algo, signature;
419 uint8_t *pkcs7_data, *name_der;
420 size_t pkcs7_data_len, name_der_len;
421 BIGNUM* serial = BN_new();
422 int sig_nid = NID_rsaEncryption;
423
Alan Stokes8b4cb962021-07-06 17:45:39 +0100424 X509_NAME* issuer_name = X509_NAME_new();
425 if (!issuer_name) {
426 return Error() << "Unable to create x509 subject name";
Martijn Coenen95194842020-09-24 16:56:46 +0200427 }
Alan Stokes8b4cb962021-07-06 17:45:39 +0100428 X509_NAME_add_entry_by_txt(issuer_name, "C", MBSTRING_ASC,
Alan Stokes35049b62021-06-25 12:16:13 +0100429 reinterpret_cast<const unsigned char*>(kIssuerCountry), -1, -1, 0);
Alan Stokes8b4cb962021-07-06 17:45:39 +0100430 X509_NAME_add_entry_by_txt(issuer_name, "O", MBSTRING_ASC,
Alan Stokes35049b62021-06-25 12:16:13 +0100431 reinterpret_cast<const unsigned char*>(kIssuerOrg), -1, -1, 0);
Alan Stokes8b4cb962021-07-06 17:45:39 +0100432 X509_NAME_add_entry_by_txt(issuer_name, "CN", MBSTRING_ASC,
433 reinterpret_cast<const unsigned char*>(kRootSubject.commonName), -1,
434 -1, 0);
Martijn Coenen95194842020-09-24 16:56:46 +0200435
Alan Stokes35049b62021-06-25 12:16:13 +0100436 BN_set_word(serial, signer.serialNumber);
Alan Stokes8b4cb962021-07-06 17:45:39 +0100437 name_der_len = i2d_X509_NAME(issuer_name, &name_der);
Martijn Coenen95194842020-09-24 16:56:46 +0200438 CBB_init(&out, 1024);
439
440 if (!CBB_add_asn1(&out, &outer_seq, CBS_ASN1_SEQUENCE) ||
441 !OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) ||
442 !CBB_add_asn1(&outer_seq, &wrapped_seq,
443 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
444 // See https://tools.ietf.org/html/rfc2315#section-9.1
445 !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) ||
446 !CBB_add_asn1_uint64(&seq, 1 /* version */) ||
447 !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
448 !CBB_add_asn1(&digest_algos_set, &digest_algo, CBS_ASN1_SEQUENCE) ||
449 !OBJ_nid2cbb(&digest_algo, NID_sha256) ||
450 !CBB_add_asn1(&digest_algo, &null, CBS_ASN1_NULL) ||
451 !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
452 !OBJ_nid2cbb(&content_info, NID_pkcs7_data) ||
453 !CBB_add_asn1(&seq, &signer_infos, CBS_ASN1_SET) ||
454 !CBB_add_asn1(&signer_infos, &signer_info, CBS_ASN1_SEQUENCE) ||
455 !CBB_add_asn1_uint64(&signer_info, 1 /* version */) ||
456 !CBB_add_asn1(&signer_info, &issuer_and_serial, CBS_ASN1_SEQUENCE) ||
457 !CBB_add_bytes(&issuer_and_serial, name_der, name_der_len) ||
458 !BN_marshal_asn1(&issuer_and_serial, serial) ||
459 !CBB_add_asn1(&signer_info, &digest_algo, CBS_ASN1_SEQUENCE) ||
460 !OBJ_nid2cbb(&digest_algo, NID_sha256) ||
461 !CBB_add_asn1(&digest_algo, &null, CBS_ASN1_NULL) ||
462 !CBB_add_asn1(&signer_info, &sign_algo, CBS_ASN1_SEQUENCE) ||
463 !OBJ_nid2cbb(&sign_algo, sig_nid) || !CBB_add_asn1(&sign_algo, &null, CBS_ASN1_NULL) ||
464 !CBB_add_asn1(&signer_info, &signature, CBS_ASN1_OCTETSTRING) ||
465 !CBB_add_bytes(&signature, signed_digest.data(), signed_digest.size()) ||
466 !CBB_finish(&out, &pkcs7_data, &pkcs7_data_len)) {
467 return Error() << "Failed to create PKCS7 certificate.";
468 }
469
470 return std::vector<uint8_t>(&pkcs7_data[0], &pkcs7_data[pkcs7_data_len]);
471}