1 #include "keymanager.h"
6 #include <boost/scoped_array.hpp>
8 #include "crypto/openssl_compat.h"
9 #include "storage/invstorage.h"
13 #include "androidkeystore.h"
20 static constexpr
bool built_with_p11 =
true;
22 static constexpr
bool built_with_p11 =
false;
25 KeyManager::KeyManager(std::shared_ptr<INvStorage> backend,
KeyManagerConfig config)
26 : backend_(std::move(backend)), config_(std::move(config)) {
28 p11_ = std_::make_unique<P11EngineGuard>(config_.p11);
32 void KeyManager::loadKeys(
const std::string *pkey_content,
const std::string *cert_content,
33 const std::string *ca_content) {
34 if (config_.tls_pkey_source == CryptoSource::kFile || config_.tls_pkey_source == CryptoSource::kAndroid) {
36 if (pkey_content !=
nullptr) {
39 backend_->loadTlsPkey(&pkey);
42 if (tmp_pkey_file ==
nullptr) {
43 tmp_pkey_file = std_::make_unique<TemporaryFile>(
"tls-pkey");
45 tmp_pkey_file->PutContents(pkey);
48 if (config_.tls_cert_source == CryptoSource::kFile || config_.tls_cert_source == CryptoSource::kAndroid) {
50 if (cert_content !=
nullptr) {
53 backend_->loadTlsCert(&cert);
56 if (tmp_cert_file ==
nullptr) {
57 tmp_cert_file = std_::make_unique<TemporaryFile>(
"tls-cert");
59 tmp_cert_file->PutContents(cert);
62 if (config_.tls_ca_source == CryptoSource::kFile || config_.tls_ca_source == CryptoSource::kAndroid) {
64 if (ca_content !=
nullptr) {
67 backend_->loadTlsCa(&ca);
70 if (tmp_ca_file ==
nullptr) {
71 tmp_ca_file = std_::make_unique<TemporaryFile>(
"tls-ca");
73 tmp_ca_file->PutContents(ca);
78 std::string KeyManager::getPkeyFile()
const {
79 std::string pkey_file;
80 if (config_.tls_pkey_source == CryptoSource::kPkcs11) {
81 if (!built_with_p11) {
82 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
84 pkey_file = (*p11_)->getTlsPkeyId();
86 if (config_.tls_pkey_source == CryptoSource::kFile || config_.tls_pkey_source == CryptoSource::kAndroid) {
87 if (tmp_pkey_file && !boost::filesystem::is_empty(tmp_pkey_file->PathString())) {
88 pkey_file = tmp_pkey_file->PathString();
94 std::string KeyManager::getCertFile()
const {
95 std::string cert_file;
96 if (config_.tls_cert_source == CryptoSource::kPkcs11) {
97 if (!built_with_p11) {
98 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
100 cert_file = (*p11_)->getTlsCertId();
102 if (config_.tls_cert_source == CryptoSource::kFile || config_.tls_cert_source == CryptoSource::kAndroid) {
103 if (tmp_cert_file && !boost::filesystem::is_empty(tmp_cert_file->PathString())) {
104 cert_file = tmp_cert_file->PathString();
110 std::string KeyManager::getCaFile()
const {
112 if (config_.tls_ca_source == CryptoSource::kPkcs11) {
113 if (!built_with_p11) {
114 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
116 ca_file = (*p11_)->getTlsCacertId();
118 if (config_.tls_ca_source == CryptoSource::kFile || config_.tls_ca_source == CryptoSource::kAndroid) {
119 if (tmp_ca_file && !boost::filesystem::is_empty(tmp_ca_file->PathString())) {
120 ca_file = tmp_ca_file->PathString();
126 std::string KeyManager::getPkey()
const {
128 if (config_.tls_pkey_source == CryptoSource::kPkcs11) {
129 if (!built_with_p11) {
130 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
132 pkey = (*p11_)->getTlsPkeyId();
134 if (config_.tls_pkey_source == CryptoSource::kFile || config_.tls_pkey_source == CryptoSource::kAndroid) {
135 backend_->loadTlsPkey(&pkey);
140 std::string KeyManager::getCert()
const {
142 if (config_.tls_cert_source == CryptoSource::kPkcs11) {
143 if (!built_with_p11) {
144 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
146 cert = (*p11_)->getTlsCertId();
148 if (config_.tls_cert_source == CryptoSource::kFile || config_.tls_cert_source == CryptoSource::kAndroid) {
149 backend_->loadTlsCert(&cert);
154 std::string KeyManager::getCa()
const {
156 if (config_.tls_ca_source == CryptoSource::kPkcs11) {
157 if (!built_with_p11) {
158 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
160 ca = (*p11_)->getTlsCacertId();
162 if (config_.tls_ca_source == CryptoSource::kFile || config_.tls_ca_source == CryptoSource::kAndroid) {
163 backend_->loadTlsCa(&ca);
168 std::string KeyManager::getCN()
const {
169 std::string not_found_cert_message =
"Certificate is not found, can't extract device_id";
171 if (config_.tls_cert_source == CryptoSource::kFile || config_.tls_cert_source == CryptoSource::kAndroid) {
172 if (!backend_->loadTlsCert(&cert)) {
173 throw std::runtime_error(not_found_cert_message);
176 if (!built_with_p11) {
177 throw std::runtime_error(
"Aktualizr was built without PKCS#11 support, can't extract device_id");
179 if (!(*p11_)->readTlsCert(&cert)) {
180 throw std::runtime_error(not_found_cert_message);
184 StructGuard<BIO> bio(BIO_new_mem_buf(const_cast<char *>(cert.c_str()), static_cast<int>(cert.size())), BIO_vfree);
185 StructGuard<X509> x(PEM_read_bio_X509(bio.get(),
nullptr,
nullptr,
nullptr), X509_free);
187 throw std::runtime_error(
"Could not parse certificate");
190 int len = X509_NAME_get_text_by_NID(X509_get_subject_name(x.get()), NID_commonName,
nullptr, 0);
192 throw std::runtime_error(
"Could not get CN from certificate");
194 boost::scoped_array<char> buf(
new char[len + 1]);
195 X509_NAME_get_text_by_NID(X509_get_subject_name(x.get()), NID_commonName, buf.get(), len + 1);
196 const std::string cn(buf.get());
200 void KeyManager::getCertInfo(std::string *subject, std::string *issuer, std::string *not_before,
201 std::string *not_after)
const {
202 std::string not_found_cert_message =
"Certificate is not found, can't extract device certificate";
204 if (config_.tls_cert_source == CryptoSource::kFile || config_.tls_cert_source == CryptoSource::kAndroid) {
205 if (!backend_->loadTlsCert(&cert)) {
206 throw std::runtime_error(not_found_cert_message);
209 if (!built_with_p11) {
210 throw std::runtime_error(
"Aktualizr was built without PKCS#11 support, can't extract device certificate");
212 if (!(*p11_)->readTlsCert(&cert)) {
213 throw std::runtime_error(not_found_cert_message);
217 StructGuard<BIO> bio(BIO_new_mem_buf(const_cast<char *>(cert.c_str()), static_cast<int>(cert.size())), BIO_vfree);
218 StructGuard<X509> x(PEM_read_bio_X509(bio.get(),
nullptr,
nullptr,
nullptr), X509_free);
220 throw std::runtime_error(
"Could not parse certificate");
223 StructGuard<BIO> subj_bio(BIO_new(BIO_s_mem()), BIO_vfree);
224 X509_NAME_print_ex(subj_bio.get(), X509_get_subject_name(x.get()), 1, 0);
225 char *subj_buf =
nullptr;
226 auto subj_len = BIO_get_mem_data(subj_bio.get(), &subj_buf);
227 if (subj_buf ==
nullptr) {
228 throw std::runtime_error(
"Could not parse certificate subject");
230 *subject = std::string(subj_buf, static_cast<size_t>(subj_len));
232 StructGuard<BIO> issuer_bio(BIO_new(BIO_s_mem()), BIO_vfree);
233 X509_NAME_print_ex(issuer_bio.get(), X509_get_issuer_name(x.get()), 1, 0);
234 char *issuer_buf =
nullptr;
235 auto issuer_len = BIO_get_mem_data(issuer_bio.get(), &issuer_buf);
236 if (issuer_buf ==
nullptr) {
237 throw std::runtime_error(
"Could not parse certificate issuer");
239 *issuer = std::string(issuer_buf, static_cast<size_t>(issuer_len));
241 #if AKTUALIZR_OPENSSL_PRE_11
242 const ASN1_TIME *nb_asn1 = X509_get_notBefore(x.get());
244 const ASN1_TIME *nb_asn1 = X509_get0_notBefore(x.get());
246 StructGuard<BIO> nb_bio(BIO_new(BIO_s_mem()), BIO_vfree);
247 ASN1_TIME_print(nb_bio.get(), nb_asn1);
249 auto nb_len = BIO_get_mem_data(nb_bio.get(), &nb_buf);
250 *not_before = std::string(nb_buf, static_cast<size_t>(nb_len));
252 #if AKTUALIZR_OPENSSL_PRE_11
253 const ASN1_TIME *na_asn1 = X509_get_notAfter(x.get());
255 const ASN1_TIME *na_asn1 = X509_get0_notAfter(x.get());
257 StructGuard<BIO> na_bio(BIO_new(BIO_s_mem()), BIO_vfree);
258 ASN1_TIME_print(na_bio.get(), na_asn1);
260 auto na_len = BIO_get_mem_data(na_bio.get(), &na_buf);
261 *not_after = std::string(na_buf, static_cast<size_t>(na_len));
265 std::string pkey = getPkey();
266 std::string cert = getCert();
267 std::string ca = getCa();
269 if ((pkey.size() != 0u) && (cert.size() != 0u) && (ca.size() != 0u)) {
270 http.setCerts(ca, config_.tls_ca_source, cert, config_.tls_cert_source, pkey, config_.tls_pkey_source);
274 Json::Value KeyManager::signTuf(
const Json::Value &in_data)
const {
275 ENGINE *crypto_engine =
nullptr;
276 std::string private_key;
277 if (config_.uptane_key_source == CryptoSource::kPkcs11) {
278 if (!built_with_p11) {
279 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
281 crypto_engine = (*p11_)->getEngine();
282 private_key = config_.p11.uptane_key_id;
286 if (config_.uptane_key_source == CryptoSource::kAndroid) {
288 b64sig = AndroidKeyStore::instance().signData(Utils::jsonToCanonicalStr(in_data));
290 throw std::runtime_error(
"Aktualizr was built without Android support");
293 if (config_.uptane_key_source == CryptoSource::kFile) {
294 backend_->loadPrimaryPrivate(&private_key);
296 b64sig = Utils::toBase64(
297 Crypto::Sign(config_.uptane_key_type, crypto_engine, private_key, Utils::jsonToCanonicalStr(in_data)));
300 Json::Value signature;
301 signature[
"method"] =
"rsassa-pss";
302 signature[
"sig"] = b64sig;
304 Json::Value out_data;
305 signature[
"keyid"] = UptanePublicKey().KeyId();
306 out_data[
"signed"] = in_data;
307 out_data[
"signatures"] = Json::Value(Json::arrayValue);
308 out_data[
"signatures"].append(signature);
312 std::string KeyManager::generateUptaneKeyPair() {
313 std::string primary_public;
315 if (config_.uptane_key_source == CryptoSource::kFile) {
316 std::string primary_private;
317 if (!backend_->loadPrimaryKeys(&primary_public, &primary_private)) {
318 bool result_ = Crypto::generateKeyPair(config_.uptane_key_type, &primary_public, &primary_private);
320 backend_->storePrimaryKeys(primary_public, primary_private);
323 if (primary_public.empty() && primary_private.empty()) {
324 throw std::runtime_error(
"Could not get uptane keys");
326 }
else if (config_.uptane_key_source == CryptoSource::kAndroid) {
328 primary_public = AndroidKeyStore::instance().getPublicKey();
329 if (primary_public.empty()) {
330 primary_public = AndroidKeyStore::instance().generateKeyPair();
333 throw std::runtime_error(
"Aktualizr was built without Android support");
335 if (primary_public.empty()) {
336 throw std::runtime_error(
"Could not get uptane keys");
339 if (!built_with_p11) {
340 throw std::runtime_error(
"Aktualizr was built without pkcs11 support!");
343 if (!(*p11_)->readUptanePublicKey(&primary_public)) {
344 (*p11_)->generateUptaneKeyPair();
347 if (primary_public.empty() && !(*p11_)->readUptanePublicKey(&primary_public)) {
348 throw std::runtime_error(
"Could not get uptane keys");
351 return primary_public;
354 PublicKey KeyManager::UptanePublicKey()
const {
355 std::string primary_public;
356 if (config_.uptane_key_source == CryptoSource::kFile) {
357 if (!backend_->loadPrimaryPublic(&primary_public)) {
358 throw std::runtime_error(
"Could not get uptane public key!");
360 }
else if (config_.uptane_key_source == CryptoSource::kAndroid) {
362 primary_public = AndroidKeyStore::instance().getPublicKey();
364 throw std::runtime_error(
"Aktualizr was built without Android support");
366 if (primary_public.empty()) {
367 throw std::runtime_error(
"Could not get uptane public key!");
370 if (!built_with_p11) {
371 throw std::runtime_error(
"Aktualizr was built without pkcs11 support!");
374 if (!(*p11_)->readUptanePublicKey(&primary_public)) {
375 throw std::runtime_error(
"Could not get uptane public key!");
378 return PublicKey(primary_public, config_.uptane_key_type);