From: Daan De Meyer Date: Tue, 5 Nov 2024 13:48:59 +0000 (+0100) Subject: openssl-util: Set default UI method instead of setting engine method X-Git-Tag: v257-rc1~5^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0bf70b1984dbef2df289a99976165cb3c90a0781;p=thirdparty%2Fsystemd.git openssl-util: Set default UI method instead of setting engine method While for engines we have ENGINE_ctrl() to set the UI method for the second PIN prompt, for openssl providers we don't have such a feature which means we get the default openssl UI for the second pin prompt. Instead, let's set the default UI method which does get used for the second pin prompt by the pkcs11 provider. --- diff --git a/src/boot/measure.c b/src/boot/measure.c index 3c409f8bd9a..a1c05a0f726 100644 --- a/src/boot/measure.c +++ b/src/boot/measure.c @@ -834,7 +834,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) { /* When signing we only support JSON output */ arg_json_format_flags &= ~SD_JSON_FORMAT_OFF; - /* This must be done before openssl_load_key_from_token() otherwise it will get stuck */ + /* This must be done before openssl_load_private_key() otherwise it will get stuck */ if (arg_certificate) { r = openssl_load_x509_certificate(arg_certificate, &certificate); if (r < 0) diff --git a/src/shared/openssl-util.c b/src/shared/openssl-util.c index 818f4a5f191..5688d541141 100644 --- a/src/shared/openssl-util.c +++ b/src/shared/openssl-util.c @@ -24,6 +24,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ENGINE*, ENGINE_free, NULL); REENABLE_WARNING; # endif +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(UI_METHOD*, UI_destroy_method, NULL); + /* For each error in the OpenSSL thread error queue, log the provided message and the OpenSSL error * string. If there are no errors in the OpenSSL thread queue, this logs the message with "No OpenSSL * errors." This logs at level debug. Returns -EIO (or -ENOMEM). */ @@ -1315,12 +1317,10 @@ int pkey_generate_volume_keys( static int load_key_from_provider( const char *provider, const char *private_key_uri, - OpenSSLAskPasswordUI *ui, EVP_PKEY **ret) { assert(provider); assert(private_key_uri); - assert(ui); assert(ret); #if OPENSSL_VERSION_MAJOR >= 3 @@ -1333,8 +1333,8 @@ static int load_key_from_provider( _cleanup_(OSSL_STORE_closep) OSSL_STORE_CTX *store = OSSL_STORE_open( private_key_uri, - ui->method, - &ui->request, + /*ui_method=*/ NULL, + /*ui_method=*/ NULL, /* post_process= */ NULL, /* post_process_data= */ NULL); if (!store) @@ -1356,10 +1356,9 @@ static int load_key_from_provider( #endif } -static int load_key_from_engine(const char *engine, const char *private_key_uri, OpenSSLAskPasswordUI *ui, EVP_PKEY **ret) { +static int load_key_from_engine(const char *engine, const char *private_key_uri, EVP_PKEY **ret) { assert(engine); assert(private_key_uri); - assert(ui); assert(ret); #if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0) @@ -1371,13 +1370,7 @@ static int load_key_from_engine(const char *engine, const char *private_key_uri, if (ENGINE_init(e) == 0) return log_openssl_errors("Failed to initialize signing engine '%s'", engine); - if (ENGINE_ctrl(e, ENGINE_CTRL_SET_USER_INTERFACE, /*i=*/ 0, ui->method, /*f=*/ NULL) <= 0) - return log_openssl_errors("Failed to set engine user interface"); - - if (ENGINE_ctrl(e, ENGINE_CTRL_SET_CALLBACK_DATA, /*i=*/ 0, &ui->request, /*f=*/ NULL) <= 0) - return log_openssl_errors("Failed to set engine user interface data"); - - _cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = ENGINE_load_private_key(e, private_key_uri, ui->method, &ui->request); + _cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = ENGINE_load_private_key(e, private_key_uri, /*ui_method=*/ NULL, /*callback_data=*/ NULL); if (!private_key) return log_openssl_errors("Failed to load private key from '%s'", private_key_uri); REENABLE_WARNING; @@ -1390,36 +1383,13 @@ static int load_key_from_engine(const char *engine, const char *private_key_uri, #endif } -int openssl_load_key_from_token( - KeySourceType private_key_source_type, - const char *private_key_source, - const char *private_key, - OpenSSLAskPasswordUI *ui, - EVP_PKEY **ret_private_key) { - - assert(IN_SET(private_key_source_type, OPENSSL_KEY_SOURCE_ENGINE, OPENSSL_KEY_SOURCE_PROVIDER)); - assert(private_key_source); - assert(ui); - assert(private_key); - - switch (private_key_source_type) { - - case OPENSSL_KEY_SOURCE_ENGINE: - return load_key_from_engine(private_key_source, private_key, ui, ret_private_key); - case OPENSSL_KEY_SOURCE_PROVIDER: - return load_key_from_provider(private_key_source, private_key, ui, ret_private_key); - default: - assert_not_reached(); - } -} - static int openssl_ask_password_ui_read(UI *ui, UI_STRING *uis) { int r; switch(UI_get_string_type(uis)) { case UIT_PROMPT: { /* If no ask password request was configured use the default openssl UI. */ - AskPasswordRequest *req = UI_get0_user_data(ui); + AskPasswordRequest *req = (AskPasswordRequest*) UI_method_get_ex_data(UI_get_method(ui), 0); if (!req) return (UI_method_get_reader(UI_OpenSSL()))(ui, uis); @@ -1448,10 +1418,41 @@ static int openssl_ask_password_ui_read(UI *ui, UI_STRING *uis) { return (UI_method_get_reader(UI_OpenSSL()))(ui, uis); } } -#endif -int openssl_ask_password_ui_new(OpenSSLAskPasswordUI **ret) { -#if HAVE_OPENSSL +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 = BIO_new_mem_buf(rawkey, rawkeysz); + if (!kb) + return log_oom_debug(); + + pk = PEM_read_bio_PrivateKey(kb, NULL, NULL, NULL); + if (!pk) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse PEM private key: %s", + ERR_error_string(ERR_get_error(), NULL)); + + if (ret) + *ret = TAKE_PTR(pk); + + return 0; +} + +static int openssl_ask_password_ui_new(const AskPasswordRequest *request, OpenSSLAskPasswordUI **ret) { assert(ret); _cleanup_(UI_destroy_methodp) UI_METHOD *method = UI_create_method("systemd-ask-password"); @@ -1467,12 +1468,31 @@ int openssl_ask_password_ui_new(OpenSSLAskPasswordUI **ret) { *ui = (OpenSSLAskPasswordUI) { .method = TAKE_PTR(method), + .request = *request, }; + UI_set_default_method(ui->method); + + if (UI_method_set_ex_data(ui->method, 0, &ui->request) == 0) + return log_openssl_errors("Failed to set extra data for UI method"); + *ret = TAKE_PTR(ui); return 0; +} +#endif + +OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) { +#if HAVE_OPENSSL + if (!ui) + return NULL; + + assert(UI_get_default_method() == ui->method); + UI_set_default_method(UI_OpenSSL()); + UI_destroy_method(ui->method); + return mfree(ui); #else - return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot create ask-password user interface."); + assert(ui == NULL); + return NULL; #endif } @@ -1531,43 +1551,6 @@ int openssl_load_x509_certificate(const char *path, X509 **ret) { #endif } -static int openssl_load_private_key_from_file(const char *path, EVP_PKEY **ret) { -#if HAVE_OPENSSL - _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 = BIO_new_mem_buf(rawkey, rawkeysz); - if (!kb) - return log_oom_debug(); - - pk = PEM_read_bio_PrivateKey(kb, NULL, NULL, NULL); - if (!pk) - return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse PEM private key: %s", - ERR_error_string(ERR_get_error(), NULL)); - - if (ret) - *ret = TAKE_PTR(pk); - - return 0; -#else - return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot load private key."); -#endif -} - int openssl_load_private_key( KeySourceType private_key_source_type, const char *private_key_source, @@ -1575,7 +1558,7 @@ int openssl_load_private_key( const AskPasswordRequest *request, EVP_PKEY **ret_private_key, OpenSSLAskPasswordUI **ret_user_interface) { - +#if HAVE_OPENSSL int r; assert(private_key); @@ -1589,18 +1572,21 @@ int openssl_load_private_key( *ret_user_interface = NULL; } else { _cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL; - r = openssl_ask_password_ui_new(&ui); + 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->request = *request; + switch (private_key_source_type) { - r = openssl_load_key_from_token( - private_key_source_type, - private_key_source, - private_key, - ui, - ret_private_key); + case OPENSSL_KEY_SOURCE_ENGINE: + r = load_key_from_engine(private_key_source, private_key, ret_private_key); + break; + case OPENSSL_KEY_SOURCE_PROVIDER: + r = load_key_from_provider(private_key_source, private_key, ret_private_key); + break; + default: + assert_not_reached(); + } if (r < 0) return log_debug_errno( r, @@ -1612,6 +1598,9 @@ int openssl_load_private_key( } return 0; +#else + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot load private key."); +#endif } int parse_openssl_key_source_argument( diff --git a/src/shared/openssl-util.h b/src/shared/openssl-util.h index f70de86a095..f7087eb3928 100644 --- a/src/shared/openssl-util.h +++ b/src/shared/openssl-util.h @@ -134,8 +134,6 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s int digest_and_sign(const EVP_MD *md, EVP_PKEY *privkey, const void *data, size_t size, void **ret, size_t *ret_size); -int openssl_load_key_from_token(KeySourceType private_key_source_type, const char *private_key_source, const char *private_key, OpenSSLAskPasswordUI *ui, EVP_PKEY **ret_private_key); - #else typedef struct X509 X509; @@ -153,41 +151,17 @@ static inline void *EVP_PKEY_free(EVP_PKEY *p) { return NULL; } -static inline void* UI_destroy_method(UI_METHOD *p) { - assert(p == NULL); - return NULL; -} - -static inline int openssl_load_key_from_token( - KeySourceType private_key_source_type, - const char *private_key_source, - const char *private_key, - OpenSSLAskPasswordUI *ui, - EVP_PKEY **ret_private_key) { - - return -EOPNOTSUPP; -} - #endif DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509*, X509_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY*, EVP_PKEY_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(UI_METHOD*, UI_destroy_method, NULL); struct OpenSSLAskPasswordUI { AskPasswordRequest request; UI_METHOD *method; }; -int openssl_ask_password_ui_new(OpenSSLAskPasswordUI **ret); - -static inline OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) { - if (!ui) - return NULL; - - UI_destroy_method(ui->method); - return mfree(ui); -} +OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OpenSSLAskPasswordUI*, openssl_ask_password_ui_free, NULL);