]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
openssl-util: Set default UI method instead of setting engine method
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 5 Nov 2024 13:48:59 +0000 (14:48 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 5 Nov 2024 18:58:45 +0000 (19:58 +0100)
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.

src/boot/measure.c
src/shared/openssl-util.c
src/shared/openssl-util.h

index 3c409f8bd9ad4706eea063b3b77c0cbf35b24437..a1c05a0f72695dc760dc5cc2840ea93f7eec3cc5 100644 (file)
@@ -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)
index 818f4a5f191d92f55435fc0a0d9aef1e0050f780..5688d5411412d0191a215e8ad6caac0df3f2bafd 100644 (file)
@@ -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(
index f70de86a0950402b199f780822bbede9b05bdf7e..f7087eb392871dce8df83aa7033c23d38bd9a42c 100644 (file)
@@ -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);