From: Yu Watanabe Date: Wed, 1 Jul 2026 18:29:29 +0000 (+0900) Subject: crypto-util: move functions X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7301e2602daed8330a84ac5a38639b143819692a;p=thirdparty%2Fsystemd.git crypto-util: move functions Implementations for loading private/public keys and X.509 certificates were scattered. Group them together to improve readability. --- diff --git a/src/shared/crypto-util.c b/src/shared/crypto-util.c index fddb2ba206b..60e2730bc7e 100644 --- a/src/shared/crypto-util.c +++ b/src/shared/crypto-util.c @@ -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,6 +2184,91 @@ static int openssl_ask_password_ui_new(const AskPasswordRequest *request, OpenSS #endif } +int openssl_load_private_key( + KeySourceType private_key_source_type, + const char *private_key_source, + const char *private_key, + const AskPasswordRequest *request, + EVP_PKEY **ret_private_key, + OpenSSLAskPasswordUI **ret_user_interface) { + + int r; + + /* The caller must keep the OpenSSLAskPasswordUI object alive as long as the EVP_PKEY object so that + * the user can enter any needed hardware token pin to unlock the private key when needed. */ + + assert(private_key); + assert(request); + assert(ret_private_key); + assert(ret_user_interface); + + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + if (private_key_source_type == OPENSSL_KEY_SOURCE_FILE) { + r = openssl_load_private_key_from_file(private_key, ret_private_key); + if (r < 0) + return r; + + *ret_user_interface = NULL; + } else { + _cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL; + r = openssl_ask_password_ui_new(request, &ui); + if (r < 0) + return log_debug_errno(r, "Failed to allocate ask-password user interface: %m"); + + UI_METHOD *ui_method = NULL; +#ifndef OPENSSL_NO_UI_CONSOLE + ui_method = ui->method; +#endif + + switch (private_key_source_type) { + + case OPENSSL_KEY_SOURCE_ENGINE: + r = load_key_from_engine(private_key_source, private_key, ui_method, ret_private_key); + break; + case OPENSSL_KEY_SOURCE_PROVIDER: + r = load_key_from_provider(private_key_source, private_key, ui_method, ret_private_key); + break; + default: + assert_not_reached(); + } + if (r < 0) + return log_debug_errno( + r, + "Failed to load key '%s' from OpenSSL private key source %s: %m", + private_key, + private_key_source); + + *ret_user_interface = TAKE_PTR(ui); + } + + return 0; +} + +int openssl_extract_public_key(EVP_PKEY *private_key, EVP_PKEY **ret) { + int r; + + assert(private_key); + assert(ret); + + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(OPENSSL_freep) void *buf = NULL; + int len = sym_i2d_PUBKEY(private_key, (unsigned char**) &buf); + if (len < 0) + return log_openssl_errors(LOG_DEBUG, "Failed to extract public key in DER format"); + + const unsigned char *t = buf; + if (!sym_d2i_PUBKEY(ret, &t, len)) + return log_openssl_errors(LOG_DEBUG, "Failed to parse public key in DER format"); + + 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; @@ -2241,18 +2338,6 @@ static int load_x509_certificate_from_provider(const char *provider, const char 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; @@ -2305,91 +2390,6 @@ int openssl_load_x509_certificate( return 0; } - -int openssl_load_private_key( - KeySourceType private_key_source_type, - const char *private_key_source, - const char *private_key, - const AskPasswordRequest *request, - EVP_PKEY **ret_private_key, - OpenSSLAskPasswordUI **ret_user_interface) { - - int r; - - /* The caller must keep the OpenSSLAskPasswordUI object alive as long as the EVP_PKEY object so that - * the user can enter any needed hardware token pin to unlock the private key when needed. */ - - assert(private_key); - assert(request); - assert(ret_private_key); - assert(ret_user_interface); - - r = dlopen_libcrypto(LOG_DEBUG); - if (r < 0) - return r; - - if (private_key_source_type == OPENSSL_KEY_SOURCE_FILE) { - r = openssl_load_private_key_from_file(private_key, ret_private_key); - if (r < 0) - return r; - - *ret_user_interface = NULL; - } else { - _cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL; - r = openssl_ask_password_ui_new(request, &ui); - if (r < 0) - return log_debug_errno(r, "Failed to allocate ask-password user interface: %m"); - - UI_METHOD *ui_method = NULL; -#ifndef OPENSSL_NO_UI_CONSOLE - ui_method = ui->method; -#endif - - switch (private_key_source_type) { - - case OPENSSL_KEY_SOURCE_ENGINE: - r = load_key_from_engine(private_key_source, private_key, ui_method, ret_private_key); - break; - case OPENSSL_KEY_SOURCE_PROVIDER: - r = load_key_from_provider(private_key_source, private_key, ui_method, ret_private_key); - break; - default: - assert_not_reached(); - } - if (r < 0) - return log_debug_errno( - r, - "Failed to load key '%s' from OpenSSL private key source %s: %m", - private_key, - private_key_source); - - *ret_user_interface = TAKE_PTR(ui); - } - - return 0; -} - -int openssl_extract_public_key(EVP_PKEY *private_key, EVP_PKEY **ret) { - int r; - - assert(private_key); - assert(ret); - - r = dlopen_libcrypto(LOG_DEBUG); - if (r < 0) - return r; - - _cleanup_(OPENSSL_freep) void *buf = NULL; - int len = sym_i2d_PUBKEY(private_key, (unsigned char**) &buf); - if (len < 0) - return log_openssl_errors(LOG_DEBUG, "Failed to extract public key in DER format"); - - const unsigned char *t = buf; - if (!sym_d2i_PUBKEY(ret, &t, len)) - return log_openssl_errors(LOG_DEBUG, "Failed to parse public key in DER format"); - - return 0; -} #endif int parse_openssl_certificate_source_argument(