crypto-util: move functions
Implementations for loading private/public keys and X.509 certificates were scattered. Group them together to improve readability.
This commit is contained in:
+165
-165
@@ -2070,6 +2070,49 @@ static int load_key_from_engine(const char *engine, const char *private_key_uri,
|
||||
#endif
|
||||
}
|
||||
|
||||
static int openssl_load_private_key_from_file(const char *path, EVP_PKEY **ret) {
|
||||
_cleanup_(erase_and_freep) char *rawkey = NULL;
|
||||
_cleanup_(BIO_freep) BIO *kb = NULL;
|
||||
_cleanup_(EVP_PKEY_freep) EVP_PKEY *pk = NULL;
|
||||
size_t rawkeysz;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(ret);
|
||||
|
||||
r = read_full_file_full(
|
||||
AT_FDCWD, path, UINT64_MAX, SIZE_MAX,
|
||||
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
|
||||
NULL,
|
||||
&rawkey, &rawkeysz);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read key file '%s': %m", path);
|
||||
|
||||
kb = sym_BIO_new_mem_buf(rawkey, rawkeysz);
|
||||
if (!kb)
|
||||
return log_oom_debug();
|
||||
|
||||
pk = sym_PEM_read_bio_PrivateKey(kb, NULL, NULL, NULL);
|
||||
if (!pk)
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to parse PEM private key");
|
||||
|
||||
*ret = TAKE_PTR(pk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) {
|
||||
if (!ui)
|
||||
return NULL;
|
||||
|
||||
#ifndef OPENSSL_NO_UI_CONSOLE
|
||||
assert(sym_UI_get_default_method() == ui->method);
|
||||
sym_UI_set_default_method(sym_UI_OpenSSL());
|
||||
sym_UI_destroy_method(ui->method);
|
||||
#endif
|
||||
return mfree(ui);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_UI_CONSOLE
|
||||
static int openssl_ask_password_ui_read(UI *ui, UI_STRING *uis) {
|
||||
int r;
|
||||
@@ -2108,37 +2151,6 @@ static int openssl_ask_password_ui_read(UI *ui, UI_STRING *uis) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static int openssl_load_private_key_from_file(const char *path, EVP_PKEY **ret) {
|
||||
_cleanup_(erase_and_freep) char *rawkey = NULL;
|
||||
_cleanup_(BIO_freep) BIO *kb = NULL;
|
||||
_cleanup_(EVP_PKEY_freep) EVP_PKEY *pk = NULL;
|
||||
size_t rawkeysz;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(ret);
|
||||
|
||||
r = read_full_file_full(
|
||||
AT_FDCWD, path, UINT64_MAX, SIZE_MAX,
|
||||
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
|
||||
NULL,
|
||||
&rawkey, &rawkeysz);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read key file '%s': %m", path);
|
||||
|
||||
kb = sym_BIO_new_mem_buf(rawkey, rawkeysz);
|
||||
if (!kb)
|
||||
return log_oom_debug();
|
||||
|
||||
pk = sym_PEM_read_bio_PrivateKey(kb, NULL, NULL, NULL);
|
||||
if (!pk)
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to parse PEM private key");
|
||||
|
||||
*ret = TAKE_PTR(pk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int openssl_ask_password_ui_new(const AskPasswordRequest *request, OpenSSLAskPasswordUI **ret) {
|
||||
#ifndef OPENSSL_NO_UI_CONSOLE
|
||||
assert(request);
|
||||
@@ -2172,140 +2184,6 @@ static int openssl_ask_password_ui_new(const AskPasswordRequest *request, OpenSS
|
||||
#endif
|
||||
}
|
||||
|
||||
static int load_x509_certificate_from_file(const char *path, X509 **ret) {
|
||||
_cleanup_free_ char *rawcert = NULL;
|
||||
_cleanup_(X509_freep) X509 *cert = NULL;
|
||||
_cleanup_(BIO_freep) BIO *cb = NULL;
|
||||
size_t rawcertsz;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(ret);
|
||||
|
||||
r = read_full_file_full(
|
||||
AT_FDCWD, path, UINT64_MAX, SIZE_MAX,
|
||||
READ_FULL_FILE_CONNECT_SOCKET,
|
||||
NULL,
|
||||
&rawcert, &rawcertsz);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read certificate file '%s': %m", path);
|
||||
|
||||
cb = sym_BIO_new_mem_buf(rawcert, rawcertsz);
|
||||
if (!cb)
|
||||
return log_oom_debug();
|
||||
|
||||
cert = sym_PEM_read_bio_X509(cb, NULL, NULL, NULL);
|
||||
if (!cert)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse X.509 certificate: %s",
|
||||
sym_ERR_error_string(sym_ERR_get_error(), NULL));
|
||||
|
||||
*ret = TAKE_PTR(cert);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_x509_certificate_from_provider(const char *provider, const char *certificate_uri, X509 **ret) {
|
||||
assert(provider);
|
||||
assert(certificate_uri);
|
||||
assert(ret);
|
||||
|
||||
/* Load the provider so that this can work without any custom written configuration in /etc/.
|
||||
* Also load the 'default' as that seems to be the recommendation. */
|
||||
if (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true))
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL provider '%s'", provider);
|
||||
if (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, "default", /* retain_fallbacks= */ true))
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL provider 'default'");
|
||||
|
||||
_cleanup_(OSSL_STORE_closep) OSSL_STORE_CTX *store = sym_OSSL_STORE_open(
|
||||
certificate_uri,
|
||||
/* ui_method= */ NULL,
|
||||
/* ui_method= */ NULL,
|
||||
/* post_process= */ NULL,
|
||||
/* post_process_data= */ NULL);
|
||||
if (!store)
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to open OpenSSL store via '%s'", certificate_uri);
|
||||
|
||||
if (sym_OSSL_STORE_expect(store, OSSL_STORE_INFO_CERT) == 0)
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to filter store by X.509 certificates");
|
||||
|
||||
_cleanup_(OSSL_STORE_INFO_freep) OSSL_STORE_INFO *info = sym_OSSL_STORE_load(store);
|
||||
if (!info)
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL store via '%s'", certificate_uri);
|
||||
|
||||
_cleanup_(X509_freep) X509 *cert = sym_OSSL_STORE_INFO_get1_CERT(info);
|
||||
if (!cert)
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to load certificate via '%s'", certificate_uri);
|
||||
|
||||
*ret = TAKE_PTR(cert);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) {
|
||||
if (!ui)
|
||||
return NULL;
|
||||
|
||||
#ifndef OPENSSL_NO_UI_CONSOLE
|
||||
assert(sym_UI_get_default_method() == ui->method);
|
||||
sym_UI_set_default_method(sym_UI_OpenSSL());
|
||||
sym_UI_destroy_method(ui->method);
|
||||
#endif
|
||||
return mfree(ui);
|
||||
}
|
||||
|
||||
int x509_fingerprint(X509 *cert, uint8_t buffer[static SHA256_DIGEST_SIZE]) {
|
||||
_cleanup_(OPENSSL_freep) void *der = NULL;
|
||||
int dersz, r;
|
||||
|
||||
assert(cert);
|
||||
|
||||
r = dlopen_libcrypto(LOG_DEBUG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
dersz = sym_i2d_X509(cert, (unsigned char**) &der);
|
||||
if (dersz < 0)
|
||||
return log_openssl_errors(LOG_DEBUG, "Unable to convert PEM certificate to DER format");
|
||||
|
||||
sha256_direct(der, dersz, buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openssl_load_x509_certificate(
|
||||
CertificateSourceType certificate_source_type,
|
||||
const char *certificate_source,
|
||||
const char *certificate,
|
||||
X509 **ret) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(certificate);
|
||||
|
||||
r = dlopen_libcrypto(LOG_DEBUG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
switch (certificate_source_type) {
|
||||
|
||||
case OPENSSL_CERTIFICATE_SOURCE_FILE:
|
||||
r = load_x509_certificate_from_file(certificate, ret);
|
||||
break;
|
||||
case OPENSSL_CERTIFICATE_SOURCE_PROVIDER:
|
||||
r = load_x509_certificate_from_provider(certificate_source, certificate, ret);
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
if (r < 0)
|
||||
return log_debug_errno(
|
||||
r,
|
||||
"Failed to load certificate '%s' from OpenSSL certificate source %s: %m",
|
||||
certificate,
|
||||
certificate_source);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openssl_load_private_key(
|
||||
KeySourceType private_key_source_type,
|
||||
const char *private_key_source,
|
||||
@@ -2390,6 +2268,128 @@ int openssl_extract_public_key(EVP_PKEY *private_key, EVP_PKEY **ret) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_x509_certificate_from_file(const char *path, X509 **ret) {
|
||||
_cleanup_free_ char *rawcert = NULL;
|
||||
_cleanup_(X509_freep) X509 *cert = NULL;
|
||||
_cleanup_(BIO_freep) BIO *cb = NULL;
|
||||
size_t rawcertsz;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(ret);
|
||||
|
||||
r = read_full_file_full(
|
||||
AT_FDCWD, path, UINT64_MAX, SIZE_MAX,
|
||||
READ_FULL_FILE_CONNECT_SOCKET,
|
||||
NULL,
|
||||
&rawcert, &rawcertsz);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read certificate file '%s': %m", path);
|
||||
|
||||
cb = sym_BIO_new_mem_buf(rawcert, rawcertsz);
|
||||
if (!cb)
|
||||
return log_oom_debug();
|
||||
|
||||
cert = sym_PEM_read_bio_X509(cb, NULL, NULL, NULL);
|
||||
if (!cert)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse X.509 certificate: %s",
|
||||
sym_ERR_error_string(sym_ERR_get_error(), NULL));
|
||||
|
||||
*ret = TAKE_PTR(cert);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_x509_certificate_from_provider(const char *provider, const char *certificate_uri, X509 **ret) {
|
||||
assert(provider);
|
||||
assert(certificate_uri);
|
||||
assert(ret);
|
||||
|
||||
/* Load the provider so that this can work without any custom written configuration in /etc/.
|
||||
* Also load the 'default' as that seems to be the recommendation. */
|
||||
if (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true))
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL provider '%s'", provider);
|
||||
if (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, "default", /* retain_fallbacks= */ true))
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL provider 'default'");
|
||||
|
||||
_cleanup_(OSSL_STORE_closep) OSSL_STORE_CTX *store = sym_OSSL_STORE_open(
|
||||
certificate_uri,
|
||||
/* ui_method= */ NULL,
|
||||
/* ui_method= */ NULL,
|
||||
/* post_process= */ NULL,
|
||||
/* post_process_data= */ NULL);
|
||||
if (!store)
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to open OpenSSL store via '%s'", certificate_uri);
|
||||
|
||||
if (sym_OSSL_STORE_expect(store, OSSL_STORE_INFO_CERT) == 0)
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to filter store by X.509 certificates");
|
||||
|
||||
_cleanup_(OSSL_STORE_INFO_freep) OSSL_STORE_INFO *info = sym_OSSL_STORE_load(store);
|
||||
if (!info)
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL store via '%s'", certificate_uri);
|
||||
|
||||
_cleanup_(X509_freep) X509 *cert = sym_OSSL_STORE_INFO_get1_CERT(info);
|
||||
if (!cert)
|
||||
return log_openssl_errors(LOG_DEBUG, "Failed to load certificate via '%s'", certificate_uri);
|
||||
|
||||
*ret = TAKE_PTR(cert);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x509_fingerprint(X509 *cert, uint8_t buffer[static SHA256_DIGEST_SIZE]) {
|
||||
_cleanup_(OPENSSL_freep) void *der = NULL;
|
||||
int dersz, r;
|
||||
|
||||
assert(cert);
|
||||
|
||||
r = dlopen_libcrypto(LOG_DEBUG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
dersz = sym_i2d_X509(cert, (unsigned char**) &der);
|
||||
if (dersz < 0)
|
||||
return log_openssl_errors(LOG_DEBUG, "Unable to convert PEM certificate to DER format");
|
||||
|
||||
sha256_direct(der, dersz, buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openssl_load_x509_certificate(
|
||||
CertificateSourceType certificate_source_type,
|
||||
const char *certificate_source,
|
||||
const char *certificate,
|
||||
X509 **ret) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(certificate);
|
||||
|
||||
r = dlopen_libcrypto(LOG_DEBUG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
switch (certificate_source_type) {
|
||||
|
||||
case OPENSSL_CERTIFICATE_SOURCE_FILE:
|
||||
r = load_x509_certificate_from_file(certificate, ret);
|
||||
break;
|
||||
case OPENSSL_CERTIFICATE_SOURCE_PROVIDER:
|
||||
r = load_x509_certificate_from_provider(certificate_source, certificate, ret);
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
if (r < 0)
|
||||
return log_debug_errno(
|
||||
r,
|
||||
"Failed to load certificate '%s' from OpenSSL certificate source %s: %m",
|
||||
certificate,
|
||||
certificate_source);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int parse_openssl_certificate_source_argument(
|
||||
|
||||
Reference in New Issue
Block a user