1 #include "keymanager.h"
5 #include <boost/scoped_array.hpp>
8 #include "storage/invstorage.h"
12 #include "androidkeystore.h"
19 static constexpr
bool built_with_p11 =
true;
21 static constexpr
bool built_with_p11 =
false;
24 KeyManager::KeyManager(std::shared_ptr<INvStorage> backend,
KeyManagerConfig config)
25 : backend_(std::move(backend)), config_(std::move(config)) {
27 p11_ = std_::make_unique<P11EngineGuard>(config_.p11);
31 void KeyManager::loadKeys(
const std::string *pkey_content,
const std::string *cert_content,
32 const std::string *ca_content) {
33 if (config_.tls_pkey_source == CryptoSource::kFile || config_.tls_pkey_source == CryptoSource::kAndroid) {
35 if (pkey_content !=
nullptr) {
38 backend_->loadTlsPkey(&pkey);
41 if (tmp_pkey_file ==
nullptr) {
42 tmp_pkey_file = std_::make_unique<TemporaryFile>(
"tls-pkey");
44 tmp_pkey_file->PutContents(pkey);
47 if (config_.tls_cert_source == CryptoSource::kFile || config_.tls_cert_source == CryptoSource::kAndroid) {
49 if (cert_content !=
nullptr) {
52 backend_->loadTlsCert(&cert);
55 if (tmp_cert_file ==
nullptr) {
56 tmp_cert_file = std_::make_unique<TemporaryFile>(
"tls-cert");
58 tmp_cert_file->PutContents(cert);
61 if (config_.tls_ca_source == CryptoSource::kFile || config_.tls_ca_source == CryptoSource::kAndroid) {
63 if (ca_content !=
nullptr) {
66 backend_->loadTlsCa(&ca);
69 if (tmp_ca_file ==
nullptr) {
70 tmp_ca_file = std_::make_unique<TemporaryFile>(
"tls-ca");
72 tmp_ca_file->PutContents(ca);
77 std::string KeyManager::getPkeyFile()
const {
78 std::string pkey_file;
79 if (config_.tls_pkey_source == CryptoSource::kPkcs11) {
80 if (!built_with_p11) {
81 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
83 pkey_file = (*p11_)->getTlsPkeyId();
85 if (config_.tls_pkey_source == CryptoSource::kFile || config_.tls_pkey_source == CryptoSource::kAndroid) {
86 if (tmp_pkey_file && !boost::filesystem::is_empty(tmp_pkey_file->PathString())) {
87 pkey_file = tmp_pkey_file->PathString();
93 std::string KeyManager::getCertFile()
const {
94 std::string cert_file;
95 if (config_.tls_cert_source == CryptoSource::kPkcs11) {
96 if (!built_with_p11) {
97 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
99 cert_file = (*p11_)->getTlsCertId();
101 if (config_.tls_cert_source == CryptoSource::kFile || config_.tls_cert_source == CryptoSource::kAndroid) {
102 if (tmp_cert_file && !boost::filesystem::is_empty(tmp_cert_file->PathString())) {
103 cert_file = tmp_cert_file->PathString();
109 std::string KeyManager::getCaFile()
const {
111 if (config_.tls_ca_source == CryptoSource::kPkcs11) {
112 if (!built_with_p11) {
113 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
115 ca_file = (*p11_)->getTlsCacertId();
117 if (config_.tls_ca_source == CryptoSource::kFile || config_.tls_ca_source == CryptoSource::kAndroid) {
118 if (tmp_ca_file && !boost::filesystem::is_empty(tmp_ca_file->PathString())) {
119 ca_file = tmp_ca_file->PathString();
125 std::string KeyManager::getPkey()
const {
127 if (config_.tls_pkey_source == CryptoSource::kPkcs11) {
128 if (!built_with_p11) {
129 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
131 pkey = (*p11_)->getTlsPkeyId();
133 if (config_.tls_pkey_source == CryptoSource::kFile || config_.tls_pkey_source == CryptoSource::kAndroid) {
134 backend_->loadTlsPkey(&pkey);
139 std::string KeyManager::getCert()
const {
141 if (config_.tls_cert_source == CryptoSource::kPkcs11) {
142 if (!built_with_p11) {
143 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
145 cert = (*p11_)->getTlsCertId();
147 if (config_.tls_cert_source == CryptoSource::kFile || config_.tls_cert_source == CryptoSource::kAndroid) {
148 backend_->loadTlsCert(&cert);
153 std::string KeyManager::getCa()
const {
155 if (config_.tls_ca_source == CryptoSource::kPkcs11) {
156 if (!built_with_p11) {
157 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
159 ca = (*p11_)->getTlsCacertId();
161 if (config_.tls_ca_source == CryptoSource::kFile || config_.tls_ca_source == CryptoSource::kAndroid) {
162 backend_->loadTlsCa(&ca);
167 std::string KeyManager::getCN()
const {
168 std::string not_found_cert_message =
"Certificate is not found, can't extract device_id";
170 if (config_.tls_cert_source == CryptoSource::kFile || config_.tls_cert_source == CryptoSource::kAndroid) {
171 if (!backend_->loadTlsCert(&cert)) {
172 throw std::runtime_error(not_found_cert_message);
175 if (!built_with_p11) {
176 throw std::runtime_error(
"Aktualizr was built without PKCS#11 support, can't extract device_id");
178 if (!(*p11_)->readTlsCert(&cert)) {
179 throw std::runtime_error(not_found_cert_message);
183 StructGuard<BIO> bio(BIO_new_mem_buf(const_cast<char *>(cert.c_str()), static_cast<int>(cert.size())), BIO_vfree);
184 StructGuard<X509> x(PEM_read_bio_X509(bio.get(),
nullptr,
nullptr,
nullptr), X509_free);
186 throw std::runtime_error(
"Could not parse certificate");
189 int len = X509_NAME_get_text_by_NID(X509_get_subject_name(x.get()), NID_commonName,
nullptr, 0);
191 throw std::runtime_error(
"Could not get CN from certificate");
193 boost::scoped_array<char> buf(
new char[len + 1]);
194 X509_NAME_get_text_by_NID(X509_get_subject_name(x.get()), NID_commonName, buf.get(), len + 1);
195 std::string cn(buf.get());
200 std::string pkey = getPkey();
201 std::string cert = getCert();
202 std::string ca = getCa();
204 if ((pkey.size() != 0u) && (cert.size() != 0u) && (ca.size() != 0u)) {
205 http.setCerts(ca, config_.tls_ca_source, cert, config_.tls_cert_source, pkey, config_.tls_pkey_source);
209 Json::Value KeyManager::signTuf(
const Json::Value &in_data)
const {
210 ENGINE *crypto_engine =
nullptr;
211 std::string private_key;
212 if (config_.uptane_key_source == CryptoSource::kPkcs11) {
213 if (!built_with_p11) {
214 throw std::runtime_error(
"Aktualizr was built without PKCS#11");
216 crypto_engine = (*p11_)->getEngine();
217 private_key = config_.p11.uptane_key_id;
221 if (config_.uptane_key_source == CryptoSource::kAndroid) {
223 b64sig = AndroidKeyStore::instance().signData(Utils::jsonToCanonicalStr(in_data));
225 throw std::runtime_error(
"Aktualizr was built without Android support");
228 if (config_.uptane_key_source == CryptoSource::kFile) {
229 backend_->loadPrimaryPrivate(&private_key);
231 b64sig = Utils::toBase64(
232 Crypto::Sign(config_.uptane_key_type, crypto_engine, private_key, Utils::jsonToCanonicalStr(in_data)));
235 Json::Value signature;
236 signature[
"method"] =
"rsassa-pss";
237 signature[
"sig"] = b64sig;
239 Json::Value out_data;
240 signature[
"keyid"] = UptanePublicKey().KeyId();
241 out_data[
"signed"] = in_data;
242 out_data[
"signatures"] = Json::Value(Json::arrayValue);
243 out_data[
"signatures"].append(signature);
247 std::string KeyManager::generateUptaneKeyPair() {
248 std::string primary_public;
250 if (config_.uptane_key_source == CryptoSource::kFile) {
251 std::string primary_private;
252 if (!backend_->loadPrimaryKeys(&primary_public, &primary_private)) {
253 bool result_ = Crypto::generateKeyPair(config_.uptane_key_type, &primary_public, &primary_private);
255 backend_->storePrimaryKeys(primary_public, primary_private);
258 if (primary_public.empty() && primary_private.empty()) {
259 throw std::runtime_error(
"Could not get uptane keys");
261 }
else if (config_.uptane_key_source == CryptoSource::kAndroid) {
263 primary_public = AndroidKeyStore::instance().getPublicKey();
264 if (primary_public.empty()) {
265 primary_public = AndroidKeyStore::instance().generateKeyPair();
268 throw std::runtime_error(
"Aktualizr was built without Android support");
270 if (primary_public.empty()) {
271 throw std::runtime_error(
"Could not get uptane keys");
274 if (!built_with_p11) {
275 throw std::runtime_error(
"Aktualizr was built without pkcs11 support!");
278 if (!(*p11_)->readUptanePublicKey(&primary_public)) {
279 (*p11_)->generateUptaneKeyPair();
282 if (primary_public.empty() && !(*p11_)->readUptanePublicKey(&primary_public)) {
283 throw std::runtime_error(
"Could not get uptane keys");
286 return primary_public;
289 PublicKey KeyManager::UptanePublicKey()
const {
290 std::string primary_public;
291 if (config_.uptane_key_source == CryptoSource::kFile) {
292 if (!backend_->loadPrimaryPublic(&primary_public)) {
293 throw std::runtime_error(
"Could not get uptane public key!");
295 }
else if (config_.uptane_key_source == CryptoSource::kAndroid) {
297 primary_public = AndroidKeyStore::instance().getPublicKey();
299 throw std::runtime_error(
"Aktualizr was built without Android support");
301 if (primary_public.empty()) {
302 throw std::runtime_error(
"Could not get uptane public key!");
305 if (!built_with_p11) {
306 throw std::runtime_error(
"Aktualizr was built without pkcs11 support!");
309 if (!(*p11_)->readUptanePublicKey(&primary_public)) {
310 throw std::runtime_error(
"Could not get uptane public key!");
313 return PublicKey(primary_public, config_.uptane_key_type);