diff options
author | Thomas Haller <thaller@redhat.com> | 2022-03-29 12:00:28 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-03-29 12:00:28 +0200 |
commit | 318776c56ddc2e83594d4c298b04d5215ae6ae29 (patch) | |
tree | ac36ebac56998f7d630a3b9a49b6d111499585a9 | |
parent | f6ee923ff568543dbb645da85b4923e5369446c8 (diff) | |
parent | 9aa02f6543f525740bb9e5594fcde835905ba6fd (diff) |
libnm: merge branch 'th/libnm-crypto'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1155
28 files changed, 575 insertions, 402 deletions
diff --git a/Makefile.am b/Makefile.am index 760b46b97a..c7d5c934e3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -110,11 +110,15 @@ include config-extra.h.mk DISTCLEANFILES += config-extra.h -$(src_libnm_core_public_mkenums_h): config-extra.h $(src_libnm_core_public_mkenums_c): config-extra.h +$(src_libnm_core_public_mkenums_h): config-extra.h +src/core/dhcp/.dirstamp: config-extra.h +src/libnm-base/.dirstamp: config-extra.h +src/libnm-client-public/.dirstamp: config-extra.h +src/libnm-client-public/.dirstamp: config-extra.h src/libnm-core-impl/.dirstamp: config-extra.h src/libnm-core-impl/.dirstamp: config-extra.h -src/libnm-base/.dirstamp: config-extra.h +src/libnm-crypto/.dirstamp: config-extra.h src/libnm-glib-aux/.dirstamp: config-extra.h src/libnm-glib-aux/tests/.dirstamp: config-extra.h src/libnm-log-core/.dirstamp: config-extra.h @@ -124,14 +128,11 @@ src/libnm-platform/tests/.dirstamp: config-extra.h src/libnm-platform/wifi/.dirstamp: config-extra.h src/libnm-platform/wpan/.dirstamp: config-extra.h src/libnm-std-aux/.dirstamp: config-extra.h -src/libnm-udev-aux/.dirstamp: config-extra.h src/libnm-systemd-shared/.dirstamp: config-extra.h src/libnm-systemd-shared/src/basic/.dirstamp: config-extra.h src/libnm-systemd-shared/src/fundamental/.dirstamp: config-extra.h src/libnm-systemd-shared/src/shared/.dirstamp: config-extra.h -src/libnm-client-public/.dirstamp: config-extra.h -src/libnm-client-public/.dirstamp: config-extra.h -src/core/dhcp/.dirstamp: config-extra.h +src/libnm-udev-aux/.dirstamp: config-extra.h ############################################################################### @@ -499,6 +500,7 @@ src_libnm_base_libnm_base_la_CPPFLAGS = \ $(NULL) src_libnm_base_libnm_base_la_SOURCES = \ + src/libnm-base/nm-base.c \ src/libnm-base/nm-base.h \ src/libnm-base/nm-config-base.h \ src/libnm-base/nm-ethtool-base.c \ @@ -1241,8 +1243,6 @@ src_libnm_core_public_mkenums_h = \ $(NULL) src_libnm_core_impl_lib_h_priv = \ src/libnm-core-impl/nm-connection-private.h \ - src/libnm-core-impl/nm-crypto-impl.h \ - src/libnm-core-impl/nm-crypto.h \ src/libnm-core-impl/nm-default-libnm-core.h \ src/libnm-core-impl/nm-property-compare.h \ src/libnm-core-impl/nm-setting-private.h \ @@ -1312,7 +1312,6 @@ src_libnm_core_impl_lib_c_settings_real = \ src_libnm_core_impl_lib_c_real = \ $(src_libnm_core_impl_lib_c_settings_real) \ src/libnm-core-impl/nm-connection.c \ - src/libnm-core-impl/nm-crypto.c \ src/libnm-core-impl/nm-dbus-utils.c \ src/libnm-core-impl/nm-errors.c \ src/libnm-core-impl/nm-keyfile-utils.c \ @@ -1413,8 +1412,6 @@ src_libnm_core_impl_libnm_core_impl_la_LDFLAGS = \ $(NULL) EXTRA_DIST += \ - src/libnm-core-impl/nm-crypto-gnutls.c \ - src/libnm-core-impl/nm-crypto-nss.c \ src/libnm-core-impl/meson.build \ $(NULL) @@ -1436,62 +1433,93 @@ dist_dependencies += \ ############################################################################### +noinst_LTLIBRARIES += src/libnm-crypto/libnm-crypto.la + +src_libnm_crypto_libnm_crypto_la_SOURCES = \ + src/libnm-crypto/nm-crypto-impl.h \ + src/libnm-crypto/nm-crypto.c \ + src/libnm-crypto/nm-crypto.h \ + $(NULL) + +src_libnm_crypto_libnm_crypto_la_CPPFLAGS = \ + $(dflt_cppflags_libnm_core) \ + $(NULL) + +src_libnm_crypto_libnm_crypto_la_LIBADD = \ + $(GLIB_LIBS) \ + $(NULL) + +src_libnm_crypto_libnm_crypto_la_LDFLAGS = \ + $(CODE_COVERAGE_LDFLAGS) \ + $(SANITIZER_LIB_LDFLAGS) \ + $(NULL) + if HAVE_CRYPTO_GNUTLS if WITH_GNUTLS -libnm_crypto_lib = src/libnm-core-impl/libnm-crypto-gnutls.la +libnm_crypto_lib = src/libnm-crypto/libnm-crypto-gnutls.la else -check_ltlibraries += src/libnm-core-impl/libnm-crypto-gnutls.la +check_ltlibraries += src/libnm-crypto/libnm-crypto-gnutls.la endif -src_libnm_core_impl_libnm_crypto_gnutls_la_SOURCES = src/libnm-core-impl/nm-crypto-gnutls.c -src_libnm_core_impl_libnm_crypto_gnutls_la_CPPFLAGS = \ +src_libnm_crypto_libnm_crypto_gnutls_la_SOURCES = src/libnm-crypto/nm-crypto-gnutls.c +src_libnm_crypto_libnm_crypto_gnutls_la_CPPFLAGS = \ $(src_libnm_core_impl_libnm_core_impl_la_CPPFLAGS) \ $(GNUTLS_CFLAGS) -src_libnm_core_impl_libnm_crypto_gnutls_la_LDFLAGS = \ +src_libnm_crypto_libnm_crypto_gnutls_la_LDFLAGS = \ $(src_libnm_core_impl_libnm_core_impl_la_LDFLAGS) -src_libnm_core_impl_libnm_crypto_gnutls_la_LIBADD = \ +src_libnm_crypto_libnm_crypto_gnutls_la_LIBADD = \ $(GLIB_LIBS) \ $(GNUTLS_LIBS) endif if HAVE_CRYPTO_NSS if WITH_NSS -libnm_crypto_lib = src/libnm-core-impl/libnm-crypto-nss.la +libnm_crypto_lib = src/libnm-crypto/libnm-crypto-nss.la else -check_ltlibraries += src/libnm-core-impl/libnm-crypto-nss.la +check_ltlibraries += src/libnm-crypto/libnm-crypto-nss.la endif -src_libnm_core_impl_libnm_crypto_nss_la_SOURCES = src/libnm-core-impl/nm-crypto-nss.c -src_libnm_core_impl_libnm_crypto_nss_la_CPPFLAGS = \ +src_libnm_crypto_libnm_crypto_nss_la_SOURCES = src/libnm-crypto/nm-crypto-nss.c +src_libnm_crypto_libnm_crypto_nss_la_CPPFLAGS = \ $(src_libnm_core_impl_libnm_core_impl_la_CPPFLAGS) \ $(NSS_CFLAGS) -src_libnm_core_impl_libnm_crypto_nss_la_LDFLAGS = \ +src_libnm_crypto_libnm_crypto_nss_la_LDFLAGS = \ $(src_libnm_core_impl_libnm_core_impl_la_LDFLAGS) -src_libnm_core_impl_libnm_crypto_nss_la_LIBADD = \ +src_libnm_crypto_libnm_crypto_nss_la_LIBADD = \ $(GLIB_LIBS) \ $(NSS_LIBS) endif if !WITH_GNUTLS if !WITH_NSS -libnm_crypto_lib = src/libnm-core-impl/libnm-crypto-null.la +libnm_crypto_lib = src/libnm-crypto/libnm-crypto-null.la else -check_ltlibraries += src/libnm-core-impl/libnm-crypto-null.la +check_ltlibraries += src/libnm-crypto/libnm-crypto-null.la endif else -check_ltlibraries += src/libnm-core-impl/libnm-crypto-null.la +check_ltlibraries += src/libnm-crypto/libnm-crypto-null.la endif -src_libnm_core_impl_libnm_crypto_null_la_SOURCES = src/libnm-core-impl/nm-crypto-null.c -src_libnm_core_impl_libnm_crypto_null_la_CPPFLAGS = \ - $(src_libnm_core_impl_libnm_core_impl_la_CPPFLAGS) -src_libnm_core_impl_libnm_crypto_null_la_LDFLAGS = \ - $(src_libnm_core_impl_libnm_core_impl_la_LDFLAGS) -src_libnm_core_impl_libnm_crypto_null_la_LIBADD = \ - $(GLIB_LIBS) +src_libnm_crypto_libnm_crypto_null_la_SOURCES = src/libnm-crypto/nm-crypto-null.c +src_libnm_crypto_libnm_crypto_null_la_CPPFLAGS = \ + $(src_libnm_core_impl_libnm_core_impl_la_CPPFLAGS) \ + $(NULL) +src_libnm_crypto_libnm_crypto_null_la_LDFLAGS = \ + $(src_libnm_core_impl_libnm_core_impl_la_LDFLAGS) \ + $(NULL) +src_libnm_crypto_libnm_crypto_null_la_LIBADD = \ + $(GLIB_LIBS) \ + $(NULL) noinst_LTLIBRARIES += $(libnm_crypto_lib) +EXTRA_DIST += \ + src/libnm-crypto/README.md \ + src/libnm-crypto/meson.build \ + src/libnm-crypto/nm-crypto-gnutls.c \ + src/libnm-crypto/nm-crypto-nss.c \ + $(NULL) + ############################################################################### check_programs += \ @@ -1545,6 +1573,7 @@ nodist_src_libnm_core_impl_tests_test_general_SOURCES = \ src_libnm_core_impl_tests_ldadd = \ src/libnm-core-aux-extern/libnm-core-aux-extern.la \ src/libnm-core-impl/libnm-core-impl.la \ + src/libnm-crypto/libnm-crypto.la \ $(libnm_crypto_lib) \ src/libnm-core-aux-intern/libnm-core-aux-intern.la \ src/libnm-base/libnm-base.la \ @@ -1778,6 +1807,7 @@ nodist_src_libnm_client_impl_libnm_client_impl_la_SOURCES = \ src_libnm_client_impl_libnm_client_impl_la_LIBADD = \ src/libnm-core-aux-extern/libnm-core-aux-extern.la \ src/libnm-core-impl/libnm-core-impl.la \ + src/libnm-crypto/libnm-crypto.la \ $(libnm_crypto_lib) \ src/libnm-core-aux-intern/libnm-core-aux-intern.la \ src/libnm-base/libnm-base.la \ @@ -2626,6 +2656,7 @@ src_core_libNetworkManager_la_LIBADD = \ src/core/libNetworkManagerBase.la \ src/libnm-core-aux-extern/libnm-core-aux-extern.la \ src/libnm-core-impl/libnm-core-impl.la \ + src/libnm-crypto/libnm-crypto.la \ $(libnm_crypto_lib) \ src/libnm-core-aux-intern/libnm-core-aux-intern.la \ src/libnm-platform/libnm-platform.la \ @@ -2771,6 +2802,7 @@ src_nm_initrd_generator_nm_initrd_generator_CPPFLAGS = \ src_nm_initrd_generator_nm_initrd_generator_LDADD = \ src/nm-initrd-generator/libnmi-core.la \ src/libnm-core-impl/libnm-core-impl.la \ + src/libnm-crypto/libnm-crypto.la \ $(libnm_crypto_lib) \ src/libnm-core-aux-intern/libnm-core-aux-intern.la \ src/libnm-platform/libnm-platform.la \ diff --git a/meson.build b/meson.build index aa782febba..f63cb22986 100644 --- a/meson.build +++ b/meson.build @@ -1094,7 +1094,9 @@ output += '\n' output += ' code coverage: ' + get_option('b_coverage').to_string() + '\n' output += ' LTO: ' + enable_lto.to_string() + '\n' output += ' Linker garbage collection: ' + enable_ld_gc.to_string() + '\n' -output += ' crypto: ' + crypto + '\n' +output += ' crypto: ' + crypto + ' (' +output += 'have-gnutls: ' + crypto_gnutls_dep.found().to_string() + ', ' +output += 'have-nss: ' + crypto_nss_dep.found().to_string() + ')\n' output += ' sanitizers: ' + get_option('b_sanitize') + '\n' output += ' Mozilla Public Suffix List: ' + enable_libpsl.to_string() + '\n' output += ' vapi: ' + enable_vapi.to_string() + '\n' diff --git a/po/POTFILES.in b/po/POTFILES.in index 548ae5a1e7..151f58fca9 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -72,10 +72,6 @@ src/libnm-client-impl/nm-vpn-service-plugin.c src/libnm-core-aux-extern/nm-libnm-core-aux.c src/libnm-core-aux-intern/nm-libnm-core-utils.c src/libnm-core-impl/nm-connection.c -src/libnm-core-impl/nm-crypto-gnutls.c -src/libnm-core-impl/nm-crypto-nss.c -src/libnm-core-impl/nm-crypto-null.c -src/libnm-core-impl/nm-crypto.c src/libnm-core-impl/nm-dbus-utils.c src/libnm-core-impl/nm-keyfile-utils.c src/libnm-core-impl/nm-keyfile.c @@ -132,6 +128,10 @@ src/libnm-core-impl/nm-team-utils.c src/libnm-core-impl/nm-utils.c src/libnm-core-impl/nm-vpn-editor-plugin.c src/libnm-core-impl/nm-vpn-plugin-info.c +src/libnm-crypto/nm-crypto-gnutls.c +src/libnm-crypto/nm-crypto-nss.c +src/libnm-crypto/nm-crypto-null.c +src/libnm-crypto/nm-crypto.c src/libnm-glib-aux/nm-shared-utils.c src/libnm-log-core/nm-logging.c src/libnmc-base/nm-client-utils.c diff --git a/src/libnm-base/meson.build b/src/libnm-base/meson.build index 1bb61020da..f4d977e986 100644 --- a/src/libnm-base/meson.build +++ b/src/libnm-base/meson.build @@ -3,6 +3,7 @@ libnm_base = static_library( 'nm-base', sources: files( + 'nm-base.c', 'nm-ethtool-base.c', 'nm-net-aux.c', 'nm-priv-helper-utils.c', diff --git a/src/libnm-base/nm-base.c b/src/libnm-base/nm-base.c new file mode 100644 index 0000000000..f81b285c4e --- /dev/null +++ b/src/libnm-base/nm-base.c @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "libnm-glib-aux/nm-default-glib-i18n-lib.h" + +#include "nm-base.h" + +/*****************************************************************************/ + +NM_CACHED_QUARK_FCN("nm-crypto-error-quark", _nm_crypto_error_quark); + +/*****************************************************************************/ diff --git a/src/libnm-base/nm-base.h b/src/libnm-base/nm-base.h index 0363e3b64b..ff062a18b8 100644 --- a/src/libnm-base/nm-base.h +++ b/src/libnm-base/nm-base.h @@ -393,4 +393,20 @@ typedef struct { #define NM_BOND_PORT_QUEUE_ID_DEF 0 +/*****************************************************************************/ + +/* NM_CRYPTO_ERROR is part of public API in libnm (implemented in libnm-core). + * We also want to use it without libnm-core. So this "_" variant is the internal + * version, with numerically same values -- to be used without libnm-base. */ + +#define _NM_CRYPTO_ERROR_FAILED 0 +#define _NM_CRYPTO_ERROR_INVALID_DATA 1 +#define _NM_CRYPTO_ERROR_INVALID_PASSWORD 2 +#define _NM_CRYPTO_ERROR_UNKNOWN_CIPHER 3 +#define _NM_CRYPTO_ERROR_DECRYPTION_FAILED 4 +#define _NM_CRYPTO_ERROR_ENCRYPTION_FAILED 5 + +#define _NM_CRYPTO_ERROR _nm_crypto_error_quark() +GQuark _nm_crypto_error_quark(void); + #endif /* __NM_LIBNM_BASE_H__ */ diff --git a/src/libnm-client-impl/nm-libnm-utils.c b/src/libnm-client-impl/nm-libnm-utils.c index d3d429eba2..951db1bc12 100644 --- a/src/libnm-client-impl/nm-libnm-utils.c +++ b/src/libnm-client-impl/nm-libnm-utils.c @@ -10,7 +10,9 @@ #include "libnm-glib-aux/nm-time-utils.h" #include "libnm-core-aux-intern/nm-common-macros.h" +#include "libnm-crypto/nm-crypto.h" #include "nm-object.h" +#include "nm-utils.h" /*****************************************************************************/ @@ -914,3 +916,58 @@ nm_utils_print(int output_mode, const char *msg) else g_return_if_reached(); } + +/*****************************************************************************/ + +/** + * nm_utils_file_is_certificate: + * @filename: name of the file to test + * + * Tests if @filename has a valid extension for an X.509 certificate file + * (".cer", ".crt", ".der", or ".pem"), and contains a certificate in a format + * recognized by NetworkManager. + * + * Returns: %TRUE if the file is a certificate, %FALSE if it is not + **/ +gboolean +nm_utils_file_is_certificate(const char *filename) +{ + g_return_val_if_fail(filename != NULL, FALSE); + + return nm_crypto_utils_file_is_certificate(filename); +} + +/** + * nm_utils_file_is_private_key: + * @filename: name of the file to test + * @out_encrypted: (out): on return, whether the file is encrypted + * + * Tests if @filename has a valid extension for an X.509 private key file + * (".der", ".key", ".pem", or ".p12"), and contains a private key in a format + * recognized by NetworkManager. + * + * Returns: %TRUE if the file is a private key, %FALSE if it is not + **/ +gboolean +nm_utils_file_is_private_key(const char *filename, gboolean *out_encrypted) +{ + g_return_val_if_fail(filename != NULL, FALSE); + + return nm_crypto_utils_file_is_private_key(filename, out_encrypted); +} + +/** + * nm_utils_file_is_pkcs12: + * @filename: name of the file to test + * + * Tests if @filename is a PKCS#<!-- -->12 file. + * + * Returns: %TRUE if the file is PKCS#<!-- -->12, %FALSE if it is not + **/ +gboolean +nm_utils_file_is_pkcs12(const char *filename) +{ + g_return_val_if_fail(filename != NULL, FALSE); + + return nm_crypto_is_pkcs12_file(filename, NULL); +} diff --git a/src/libnm-client-public/NetworkManager.h b/src/libnm-client-public/NetworkManager.h index 3134562e61..66f676a111 100644 --- a/src/libnm-client-public/NetworkManager.h +++ b/src/libnm-client-public/NetworkManager.h @@ -120,8 +120,8 @@ #if !defined(NETWORKMANAGER_COMPILATION) \ && (!defined(NM_NO_INCLUDE_EXTRA_HEADERS) || !NM_NO_INCLUDE_EXTRA_HEADERS) /* historically, NetworkManager.h drags in the following system headers. - * These are not strictly necessary and the user may wish to opt out from - * including them. */ + * These are not strictly necessary and the user may wish to opt out from + * including them. */ #include <linux/if_ether.h> #include <linux/if_infiniband.h> #include <linux/if_vlan.h> diff --git a/src/libnm-client-public/nm-client.h b/src/libnm-client-public/nm-client.h index 8b00eab095..2e3e77c43c 100644 --- a/src/libnm-client-public/nm-client.h +++ b/src/libnm-client-public/nm-client.h @@ -496,6 +496,10 @@ gboolean nm_client_dbus_set_property_finish(NMClient *client, GAsyncResult *resu NM_AVAILABLE_IN_1_30 void nm_utils_print(int output_mode, const char *msg); +gboolean nm_utils_file_is_certificate(const char *filename); +gboolean nm_utils_file_is_private_key(const char *filename, gboolean *out_encrypted); +gboolean nm_utils_file_is_pkcs12(const char *filename); + G_END_DECLS #endif /* __NM_CLIENT_H__ */ diff --git a/src/libnm-core-impl/meson.build b/src/libnm-core-impl/meson.build index 3ee044fe10..83c290857c 100644 --- a/src/libnm-core-impl/meson.build +++ b/src/libnm-core-impl/meson.build @@ -2,45 +2,6 @@ libnm_core_impl_inc = include_directories('.') -if crypto_nss_dep.found() - libnm_crypto_nss = static_library( - 'nm-crypto-nss', - sources: 'nm-crypto-nss.c', - dependencies: [ - libnm_core_public_dep, - crypto_nss_dep, - ], - ) -endif - -if crypto_gnutls_dep.found() - libnm_crypto_gnutls = static_library( - 'nm-crypto-gnutls', - sources: 'nm-crypto-gnutls.c', - dependencies: [ - libnm_core_public_dep, - crypto_gnutls_dep, - ], - ) -endif - -libnm_crypto_null = static_library( - 'nm-crypto-null', - sources: 'nm-crypto-null.c', - dependencies: [ - libnm_core_public_dep, - ], -) - -if crypto == 'nss' - libnm_crypto = libnm_crypto_nss -elif crypto == 'gnutls' - libnm_crypto = libnm_crypto_gnutls -else - assert(crypto == 'null', 'Unexpected setting "crypto=' + crypto + '"') - libnm_crypto = libnm_crypto_null -endif - libnm_core_settings_sources = files( 'nm-setting-6lowpan.c', 'nm-setting-8021x.c', @@ -99,7 +60,6 @@ libnm_core_settings_sources = files( libnm_core_impl_sources = files( 'nm-connection.c', - 'nm-crypto.c', 'nm-dbus-utils.c', 'nm-errors.c', 'nm-keyfile-utils.c', diff --git a/src/libnm-core-impl/nm-errors.c b/src/libnm-core-impl/nm-errors.c index ea4ca5e9e6..fad854bc2d 100644 --- a/src/libnm-core-impl/nm-errors.c +++ b/src/libnm-core-impl/nm-errors.c @@ -12,12 +12,24 @@ NM_CACHED_QUARK_FCN("nm-agent-manager-error-quark", nm_agent_manager_error_quark); NM_CACHED_QUARK_FCN("nm-connection-error-quark", nm_connection_error_quark); -NM_CACHED_QUARK_FCN("nm-crypto-error-quark", nm_crypto_error_quark); NM_CACHED_QUARK_FCN("nm-device-error-quark", nm_device_error_quark); NM_CACHED_QUARK_FCN("nm-secret-agent-error-quark", nm_secret_agent_error_quark); NM_CACHED_QUARK_FCN("nm-settings-error-quark", nm_settings_error_quark); NM_CACHED_QUARK_FCN("nm-vpn-plugin-error-quark", nm_vpn_plugin_error_quark); +GQuark +nm_crypto_error_quark(void) +{ + G_STATIC_ASSERT(NM_CRYPTO_ERROR_FAILED == _NM_CRYPTO_ERROR_FAILED); + G_STATIC_ASSERT(NM_CRYPTO_ERROR_INVALID_DATA == _NM_CRYPTO_ERROR_INVALID_DATA); + G_STATIC_ASSERT(NM_CRYPTO_ERROR_INVALID_PASSWORD == _NM_CRYPTO_ERROR_INVALID_PASSWORD); + G_STATIC_ASSERT(NM_CRYPTO_ERROR_UNKNOWN_CIPHER == _NM_CRYPTO_ERROR_UNKNOWN_CIPHER); + G_STATIC_ASSERT(NM_CRYPTO_ERROR_DECRYPTION_FAILED == _NM_CRYPTO_ERROR_DECRYPTION_FAILED); + G_STATIC_ASSERT(NM_CRYPTO_ERROR_ENCRYPTION_FAILED == _NM_CRYPTO_ERROR_ENCRYPTION_FAILED); + + return _nm_crypto_error_quark(); +} + static void register_error_domain(GQuark domain, const char *interface, GType enum_type) { diff --git a/src/libnm-core-impl/nm-setting-8021x.c b/src/libnm-core-impl/nm-setting-8021x.c index fa0a3057fe..dce35cf016 100644 --- a/src/libnm-core-impl/nm-setting-8021x.c +++ b/src/libnm-core-impl/nm-setting-8021x.c @@ -9,8 +9,8 @@ #include "nm-setting-8021x.h" #include "libnm-glib-aux/nm-secret-utils.h" +#include "libnm-crypto/nm-crypto.h" #include "nm-utils.h" -#include "nm-crypto.h" #include "nm-utils-private.h" #include "nm-setting-private.h" #include "nm-core-enum-types.h" @@ -516,7 +516,7 @@ _cert_impl_set(NMSetting8021x *setting, gs_unref_bytes GBytes *file = NULL; if (NM_IN_SET(property, PROP_PRIVATE_KEY, PROP_PHASE2_PRIVATE_KEY)) { - file = nm_crypto_read_file(value, error); + file = nm_utils_read_crypto_file_to_bytes(value, error); if (!file) goto err; format = nm_crypto_verify_private_key_data(g_bytes_get_data(file, NULL), diff --git a/src/libnm-core-impl/nm-utils.c b/src/libnm-core-impl/nm-utils.c index 55b01c159b..d5d884f2e4 100644 --- a/src/libnm-core-impl/nm-utils.c +++ b/src/libnm-core-impl/nm-utils.c @@ -27,7 +27,6 @@ #include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-utils-private.h" #include "nm-setting-private.h" -#include "nm-crypto.h" #include "nm-setting-bond.h" #include "nm-setting-bond-port.h" #include "nm-setting-bridge.h" @@ -3083,94 +3082,6 @@ nm_utils_uuid_generate(void) /*****************************************************************************/ -static gboolean -file_has_extension(const char *filename, const char *extensions[]) -{ - const char *ext; - gsize i; - - ext = strrchr(filename, '.'); - if (!ext) - return FALSE; - - for (i = 0; extensions[i]; i++) { - if (!g_ascii_strcasecmp(ext, extensions[i])) - return TRUE; - } - - return FALSE; -} - -/** - * nm_utils_file_is_certificate: - * @filename: name of the file to test - * - * Tests if @filename has a valid extension for an X.509 certificate file - * (".cer", ".crt", ".der", or ".pem"), and contains a certificate in a format - * recognized by NetworkManager. - * - * Returns: %TRUE if the file is a certificate, %FALSE if it is not - **/ -gboolean -nm_utils_file_is_certificate(const char *filename) -{ - const char *extensions[] = {".der", ".pem", ".crt", ".cer", NULL}; - NMCryptoFileFormat file_format; - - g_return_val_if_fail(filename != NULL, FALSE); - - if (!file_has_extension(filename, extensions)) - return FALSE; - - if (!nm_crypto_load_and_verify_certificate(filename, &file_format, NULL, NULL)) - return FALSE; - return file_format = NM_CRYPTO_FILE_FORMAT_X509; -} - -/** - * nm_utils_file_is_private_key: - * @filename: name of the file to test - * @out_encrypted: (out): on return, whether the file is encrypted - * - * Tests if @filename has a valid extension for an X.509 private key file - * (".der", ".key", ".pem", or ".p12"), and contains a private key in a format - * recognized by NetworkManager. - * - * Returns: %TRUE if the file is a private key, %FALSE if it is not - **/ -gboolean -nm_utils_file_is_private_key(const char *filename, gboolean *out_encrypted) -{ - const char *extensions[] = {".der", ".pem", ".p12", ".key", NULL}; - - g_return_val_if_fail(filename != NULL, FALSE); - - NM_SET_OUT(out_encrypted, FALSE); - if (!file_has_extension(filename, extensions)) - return FALSE; - - return nm_crypto_verify_private_key(filename, NULL, out_encrypted, NULL) - != NM_CRYPTO_FILE_FORMAT_UNKNOWN; -} - -/** - * nm_utils_file_is_pkcs12: - * @filename: name of the file to test - * - * Tests if @filename is a PKCS#<!-- -->12 file. - * - * Returns: %TRUE if the file is PKCS#<!-- -->12, %FALSE if it is not - **/ -gboolean -nm_utils_file_is_pkcs12(const char *filename) -{ - g_return_val_if_fail(filename != NULL, FALSE); - - return nm_crypto_is_pkcs12_file(filename, NULL); -} - -/*****************************************************************************/ - gboolean _nm_utils_check_file(const char *filename, gint64 check_owner, @@ -3795,22 +3706,13 @@ nm_utils_hwaddr_aton(const char *asc, gpointer buffer, gsize length) char * nm_utils_bin2hexstr(gconstpointer src, gsize len, int final_len) { - char *result; gsize buflen = (len * 2) + 1; g_return_val_if_fail(src != NULL, NULL); g_return_val_if_fail(len > 0 && (buflen - 1) / 2 == len, NULL); g_return_val_if_fail(final_len < 0 || (gsize) final_len < buflen, NULL); - result = g_malloc(buflen); - - nm_utils_bin2hexstr_full(src, len, '\0', FALSE, result); - - /* Cut converted key off at the correct length for this cipher type */ - if (final_len >= 0 && (gsize) final_len < buflen) - result[final_len] = '\0'; - - return result; + return _nm_utils_bin2hexstr(src, len, final_len); } /** diff --git a/src/libnm-core-impl/tests/test-crypto.c b/src/libnm-core-impl/tests/test-crypto.c index 6a6e7fbc80..896c3c2e69 100644 --- a/src/libnm-core-impl/tests/test-crypto.c +++ b/src/libnm-core-impl/tests/test-crypto.c @@ -10,7 +10,7 @@ #include <stdlib.h> #include <stdio.h> -#include "nm-crypto-impl.h" +#include "libnm-crypto/nm-crypto-impl.h" #include "nm-utils.h" #include "nm-errors.h" #include "libnm-core-intern/nm-core-internal.h" @@ -92,7 +92,7 @@ test_cert(gconstpointer test_data) nmtst_assert_success(success, error); g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_X509); - g_assert(nm_utils_file_is_certificate(path)); + g_assert(nm_crypto_utils_file_is_certificate(path)); } static void @@ -106,7 +106,7 @@ test_load_private_key(const char *path, gs_unref_bytes GBytes *array = NULL; GError *error = NULL; - g_assert(nm_utils_file_is_private_key(path, &is_encrypted)); + g_assert(nm_crypto_utils_file_is_private_key(path, &is_encrypted)); g_assert(is_encrypted); array = nmtst_crypto_decrypt_openssl_private_key(path, password, &key_type, &error); @@ -146,7 +146,7 @@ test_load_pkcs12(const char *path, const char *password, int expected_error) gboolean is_encrypted = FALSE; GError *error = NULL; - g_assert(nm_utils_file_is_private_key(path, NULL)); + g_assert(nm_crypto_utils_file_is_private_key(path, NULL)); format = nm_crypto_verify_private_key(path, password, &is_encrypted, &error); if (expected_error != -1) { @@ -167,7 +167,7 @@ test_load_pkcs12_no_password(const char *path) gboolean is_encrypted = FALSE; GError *error = NULL; - g_assert(nm_utils_file_is_private_key(path, NULL)); + g_assert(nm_crypto_utils_file_is_private_key(path, NULL)); /* We should still get a valid returned crypto file format */ format = nm_crypto_verify_private_key(path, NULL, &is_encrypted, &error); @@ -201,7 +201,7 @@ test_load_pkcs8(const char *path, const char *password, int expected_error) gboolean is_encrypted = FALSE; GError *error = NULL; - g_assert(nm_utils_file_is_private_key(path, NULL)); + g_assert(nm_crypto_utils_file_is_private_key(path, NULL)); format = nm_crypto_verify_private_key(path, password, &is_encrypted, &error); if (expected_error != -1) { @@ -285,7 +285,7 @@ test_key_decrypted(gconstpointer test_data) path = g_build_filename(TEST_CERT_DIR, file, NULL); - g_assert(nm_utils_file_is_private_key(path, &is_encrypted)); + g_assert(nm_crypto_utils_file_is_private_key(path, &is_encrypted)); g_assert(!is_encrypted); g_free(path); @@ -399,6 +399,23 @@ test_md5(void) } } +/*****************************************************************************/ + +static void +test_crypto_error(void) +{ + G_STATIC_ASSERT(NM_CRYPTO_ERROR_FAILED == _NM_CRYPTO_ERROR_FAILED); + G_STATIC_ASSERT(NM_CRYPTO_ERROR_INVALID_DATA == _NM_CRYPTO_ERROR_INVALID_DATA); + G_STATIC_ASSERT(NM_CRYPTO_ERROR_INVALID_PASSWORD == _NM_CRYPTO_ERROR_INVALID_PASSWORD); + G_STATIC_ASSERT(NM_CRYPTO_ERROR_UNKNOWN_CIPHER == _NM_CRYPTO_ERROR_UNKNOWN_CIPHER); + G_STATIC_ASSERT(NM_CRYPTO_ERROR_DECRYPTION_FAILED == _NM_CRYPTO_ERROR_DECRYPTION_FAILED); + G_STATIC_ASSERT(NM_CRYPTO_ERROR_ENCRYPTION_FAILED == _NM_CRYPTO_ERROR_ENCRYPTION_FAILED); + + g_assert_cmpint(NM_CRYPTO_ERROR, ==, _NM_CRYPTO_ERROR); +} + +/*****************************************************************************/ + NMTST_DEFINE(); int @@ -448,6 +465,7 @@ main(int argc, char **argv) g_test_add_data_func("/libnm/crypto/PKCS#8", "pkcs8-enc-key.pem, 1234567890", test_pkcs8); g_test_add_func("/libnm/crypto/md5", test_md5); + g_test_add_func("/libnm/crypto/error", test_crypto_error); ret = g_test_run(); diff --git a/src/libnm-core-public/nm-utils.h b/src/libnm-core-public/nm-utils.h index 0a7c7a8136..5faed75a36 100644 --- a/src/libnm-core-public/nm-utils.h +++ b/src/libnm-core-public/nm-utils.h @@ -111,10 +111,6 @@ GPtrArray *nm_utils_ip_routes_from_variant(GVariant *value, int family); char *nm_utils_uuid_generate(void); -gboolean nm_utils_file_is_certificate(const char *filename); -gboolean nm_utils_file_is_private_key(const char *filename, gboolean *out_encrypted); -gboolean nm_utils_file_is_pkcs12(const char *filename); - typedef gboolean (*NMUtilsFileSearchInPathsPredicate)(const char *filename, gpointer user_data); struct stat; diff --git a/src/libnm-crypto/README.md b/src/libnm-crypto/README.md new file mode 100644 index 0000000000..5e83eb0188 --- /dev/null +++ b/src/libnm-crypto/README.md @@ -0,0 +1,7 @@ +libnm-crypto +============ + +libnm-core has a dependency on crypto code (either backed by +"gnutls", "nss" or the "null" dummy implementation). + +libnm-core gets then statically linked into the daemon and into libnm.so. diff --git a/src/libnm-crypto/meson.build b/src/libnm-crypto/meson.build new file mode 100644 index 0000000000..9134c929f1 --- /dev/null +++ b/src/libnm-crypto/meson.build @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +if crypto_nss_dep.found() + libnm_crypto_nss = static_library( + 'nm-crypto-nss', + sources: 'nm-crypto-nss.c', + include_directories: [ + top_inc, + src_inc, + ], + dependencies: [ + glib_dep, + crypto_nss_dep, + ], + ) +endif + +if crypto_gnutls_dep.found() + libnm_crypto_gnutls = static_library( + 'nm-crypto-gnutls', + sources: 'nm-crypto-gnutls.c', + include_directories: [ + top_inc, + src_inc, + ], + dependencies: [ + glib_dep, + crypto_gnutls_dep, + ], + ) +endif + +libnm_crypto_null = static_library( + 'nm-crypto-null', + sources: 'nm-crypto-null.c', + include_directories: [ + top_inc, + src_inc, + ], + dependencies: [ + glib_dep, + ], +) + +if crypto == 'nss' + libnm_crypto_impl = libnm_crypto_nss +elif crypto == 'gnutls' + libnm_crypto_impl = libnm_crypto_gnutls +else + assert(crypto == 'null', 'Unexpected setting "crypto=' + crypto + '"') + libnm_crypto_impl = libnm_crypto_null +endif + +libnm_crypto = static_library( + 'nm-crypto', + sources: [ + 'nm-crypto.c', + ], + include_directories: [ + top_inc, + src_inc, + ], + link_with: [ + libnm_crypto_impl, + ], + dependencies: [ + glib_dep, + ], +) diff --git a/src/libnm-core-impl/nm-crypto-gnutls.c b/src/libnm-crypto/nm-crypto-gnutls.c index d9e5913645..60adf4d3f0 100644 --- a/src/libnm-core-impl/nm-crypto-gnutls.c +++ b/src/libnm-crypto/nm-crypto-gnutls.c @@ -14,7 +14,6 @@ #include <gnutls/pkcs12.h> #include "libnm-glib-aux/nm-secret-utils.h" -#include "nm-errors.h" /*****************************************************************************/ @@ -54,8 +53,8 @@ _nm_crypto_init(GError **error) if (gnutls_global_init() != 0) { gnutls_global_deinit(); g_set_error_literal(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Failed to initialize the crypto engine.")); return FALSE; } @@ -87,8 +86,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, if (!_get_cipher_info(cipher, &cipher_mech, &real_iv_len)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_UNKNOWN_CIPHER, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_UNKNOWN_CIPHER, _("Unsupported key cipher for decryption")); return NULL; } @@ -98,8 +97,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, if (iv_len < real_iv_len) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Invalid IV length (must be at least %u)."), (guint) real_iv_len); return NULL; @@ -116,8 +115,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, err = gnutls_cipher_init(&ctx, cipher_mech, &key_dt, &iv_dt); if (err < 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to initialize the decryption cipher context: %s (%s)"), gnutls_strerror_name(err), gnutls_strerror(err)); @@ -130,8 +129,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, if (err < 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: %s (%s)"), gnutls_strerror_name(err), gnutls_strerror(err)); @@ -143,8 +142,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, /* Check if the padding at the end of the decrypted data is valid */ if (pad_len == 0 || pad_len > real_iv_len) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: unexpected padding length.")); return NULL; } @@ -155,8 +154,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, for (pad_i = 1; pad_i <= pad_len; ++pad_i) { if (output.bin[data_len - pad_i] != pad_len) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key.")); return NULL; } @@ -189,8 +188,8 @@ _nmtst_crypto_encrypt(NMCryptoCipherType cipher, if (cipher == NM_CRYPTO_CIPHER_DES_CBC || !_get_cipher_info(cipher, &cipher_mech, NULL)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_UNKNOWN_CIPHER, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_UNKNOWN_CIPHER, _("Unsupported key cipher for encryption")); return NULL; } @@ -206,8 +205,8 @@ _nmtst_crypto_encrypt(NMCryptoCipherType cipher, err = gnutls_cipher_init(&ctx, cipher_mech, &key_dt, &iv_dt); if (err < 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to initialize the encryption cipher context: %s (%s)"), gnutls_strerror_name(err), gnutls_strerror(err)); @@ -234,8 +233,8 @@ _nmtst_crypto_encrypt(NMCryptoCipherType cipher, if (err < 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to encrypt the data: %s (%s)"), gnutls_strerror_name(err), gnutls_strerror(err)); @@ -259,8 +258,8 @@ _nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error) err = gnutls_x509_crt_init(&der); if (err < 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Error initializing certificate data: %s"), gnutls_strerror(err)); return FALSE; @@ -282,8 +281,8 @@ _nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error) return TRUE; g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode certificate: %s"), gnutls_strerror(err)); return FALSE; @@ -307,8 +306,8 @@ _nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *passwor err = gnutls_pkcs12_init(&p12); if (err < 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Couldn't initialize PKCS#12 decoder: %s"), gnutls_strerror(err)); return FALSE; @@ -321,8 +320,8 @@ _nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *passwor err = gnutls_pkcs12_import(p12, &dt, GNUTLS_X509_FMT_PEM, 0); if (err < 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode PKCS#12 file: %s"), gnutls_strerror(err)); gnutls_pkcs12_deinit(p12); @@ -331,18 +330,18 @@ _nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *passwor } err = gnutls_pkcs12_verify_mac(p12, password); - - gnutls_pkcs12_deinit(p12); - if (err != GNUTLS_E_SUCCESS) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Couldn't verify PKCS#12 file: %s"), gnutls_strerror(err)); + gnutls_pkcs12_deinit(p12); return FALSE; } + gnutls_pkcs12_deinit(p12); + return TRUE; } @@ -365,8 +364,8 @@ _nm_crypto_verify_pkcs8(const guint8 *data, err = gnutls_x509_privkey_init(&p8); if (err < 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Couldn't initialize PKCS#8 decoder: %s"), gnutls_strerror(err)); return FALSE; @@ -393,8 +392,8 @@ _nm_crypto_verify_pkcs8(const guint8 *data, */ } else { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode PKCS#8 file: %s"), gnutls_strerror(err)); return FALSE; diff --git a/src/libnm-core-impl/nm-crypto-impl.h b/src/libnm-crypto/nm-crypto-impl.h index 61c3f7f8e2..0b7c14dc08 100644 --- a/src/libnm-core-impl/nm-crypto-impl.h +++ b/src/libnm-crypto/nm-crypto-impl.h @@ -8,6 +8,7 @@ #define __NM_CRYPTO_IMPL_H__ #include "nm-crypto.h" +#include "libnm-base/nm-base.h" gboolean _nm_crypto_init(GError **error); diff --git a/src/libnm-core-impl/nm-crypto-nss.c b/src/libnm-crypto/nm-crypto-nss.c index c27bf09e35..b31ca55ee0 100644 --- a/src/libnm-core-impl/nm-crypto-nss.c +++ b/src/libnm-crypto/nm-crypto-nss.c @@ -21,7 +21,7 @@ NM_PRAGMA_WARNING_DISABLE("-Wstrict-prototypes") NM_PRAGMA_WARNING_REENABLE #include "libnm-glib-aux/nm-secret-utils.h" -#include "nm-errors.h" +#include "libnm-base/nm-base.h" /*****************************************************************************/ @@ -65,8 +65,8 @@ _nm_crypto_init(GError **error) ret = NSS_NoDB_Init(NULL); if (ret != SECSuccess) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Failed to initialize the crypto engine: %d."), PR_GetError()); PR_Cleanup(); @@ -113,16 +113,16 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, if (!_get_cipher_info(cipher, &cipher_mech, &real_iv_len)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_UNKNOWN_CIPHER, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_UNKNOWN_CIPHER, _("Unsupported key cipher for decryption")); return NULL; } if (iv_len < real_iv_len) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Invalid IV length (must be at least %u)."), (guint) real_iv_len); return NULL; @@ -134,8 +134,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, slot = PK11_GetBestSlot(cipher_mech, NULL); if (!slot) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Failed to initialize the decryption cipher slot.")); goto out; } @@ -145,8 +145,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, sym_key = PK11_ImportSymKey(slot, cipher_mech, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, NULL); if (!sym_key) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to set symmetric key for decryption.")); goto out; } @@ -156,8 +156,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, sec_param = PK11_ParamFromIV(cipher_mech, &key_item); if (!sec_param) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to set IV for decryption.")); goto out; } @@ -165,8 +165,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, ctx = PK11_CreateContextBySymKey(cipher_mech, CKA_DECRYPT, sym_key, sec_param); if (!ctx) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to initialize the decryption context.")); goto out; } @@ -182,8 +182,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, data_len); if (s != SECSuccess) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: %d."), PORT_GetError()); goto out; @@ -191,8 +191,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, if (decrypted_len > data_len) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: decrypted data too large.")); goto out; } @@ -203,8 +203,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, data_len - decrypted_len); if (s != SECSuccess) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to finalize decryption of the private key: %d."), PORT_GetError()); goto out; @@ -216,8 +216,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, /* Check if the padding at the end of the decrypted data is valid */ if (pad_len == 0 || pad_len > real_iv_len) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: unexpected padding length.")); goto out; } @@ -228,8 +228,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, for (i = pad_len; i > 0; i--) { if (output.bin[data_len - i] != pad_len) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key.")); goto out; } @@ -283,8 +283,8 @@ _nmtst_crypto_encrypt(NMCryptoCipherType cipher, if (cipher == NM_CRYPTO_CIPHER_DES_CBC || !_get_cipher_info(cipher, &cipher_mech, NULL)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_UNKNOWN_CIPHER, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_UNKNOWN_CIPHER, _("Unsupported key cipher for encryption")); return NULL; } @@ -295,8 +295,8 @@ _nmtst_crypto_encrypt(NMCryptoCipherType cipher, slot = PK11_GetBestSlot(cipher_mech, NULL); if (!slot) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Failed to initialize the encryption cipher slot.")); return NULL; } @@ -304,8 +304,8 @@ _nmtst_crypto_encrypt(NMCryptoCipherType cipher, sym_key = PK11_ImportSymKey(slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); if (!sym_key) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to set symmetric key for encryption.")); goto out; } @@ -313,8 +313,8 @@ _nmtst_crypto_encrypt(NMCryptoCipherType cipher, sec_param = PK11_ParamFromIV(cipher_mech, &iv_item); if (!sec_param) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to set IV for encryption.")); goto out; } @@ -322,8 +322,8 @@ _nmtst_crypto_encrypt(NMCryptoCipherType cipher, ctx = PK11_CreateContextBySymKey(cipher_mech, CKA_ENCRYPT, sym_key, sec_param); if (!ctx) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to initialize the encryption context.")); goto out; } @@ -347,8 +347,8 @@ _nmtst_crypto_encrypt(NMCryptoCipherType cipher, PK11_CipherOp(ctx, output.bin, &encrypted_len, output.len, padded_buf.bin, padded_buf.len); if (ret != SECSuccess) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to encrypt: %d."), PORT_GetError()); goto out; @@ -356,8 +356,8 @@ _nmtst_crypto_encrypt(NMCryptoCipherType cipher, if (encrypted_len != output.len) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Unexpected amount of data after encrypting.")); goto out; } @@ -393,8 +393,8 @@ _nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error) cert = CERT_DecodeCertFromPackage((char *) data, len); if (!cert) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode certificate: %d"), PORT_GetError()); return FALSE; @@ -438,8 +438,8 @@ _nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *passwor if (!ucs2_password.bin || ucs2_password.len == 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_PASSWORD, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_PASSWORD, _("Password must be UTF-8")); return FALSE; } @@ -461,15 +461,18 @@ _nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *passwor slot = PK11_GetInternalKeySlot(); if (!slot) { - g_set_error(error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Couldn't initialize slot")); + g_set_error(error, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, + _("Couldn't initialize slot")); goto out; } p12ctx = SEC_PKCS12DecoderStart(&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL); if (!p12ctx) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Couldn't initialize PKCS#12 decoder: %d"), PORT_GetError()); goto out; @@ -478,8 +481,8 @@ _nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *passwor s = SEC_PKCS12DecoderUpdate(p12ctx, (guint8 *) data, data_len); if (s != SECSuccess) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode PKCS#12 file: %d"), PORT_GetError()); goto out; @@ -488,8 +491,8 @@ _nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *passwor s = SEC_PKCS12DecoderVerify(p12ctx); if (s != SECSuccess) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Couldn't verify PKCS#12 file: %d"), PORT_GetError()); goto out; @@ -506,6 +509,7 @@ out: if (pw.data) SECITEM_ZfreeItem(&pw, PR_FALSE); + nm_assert(!error || (success == (!*error))); return success; } @@ -539,8 +543,8 @@ _nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error) s = PK11_GenerateRandom(buffer, buffer_len); if (s != SECSuccess) { g_set_error_literal(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Could not generate random data.")); return FALSE; } diff --git a/src/libnm-core-impl/nm-crypto-null.c b/src/libnm-crypto/nm-crypto-null.c index 2f072257ec..6f6c7f2897 100644 --- a/src/libnm-core-impl/nm-crypto-null.c +++ b/src/libnm-crypto/nm-crypto-null.c @@ -9,7 +9,6 @@ #include "nm-crypto-impl.h" #include "libnm-glib-aux/nm-secret-utils.h" -#include "nm-errors.h" /*****************************************************************************/ @@ -17,8 +16,8 @@ gboolean _nm_crypto_init(GError **error) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Compiled without crypto support.")); return FALSE; } @@ -35,8 +34,8 @@ _nmtst_crypto_decrypt(NMCryptoCipherType cipher, GError **error) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Compiled without crypto support.")); return NULL; } @@ -53,8 +52,8 @@ _nmtst_crypto_encrypt(NMCryptoCipherType cipher, GError **error) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Compiled without crypto support.")); return NULL; } @@ -63,8 +62,8 @@ gboolean _nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Compiled without crypto support.")); return FALSE; } @@ -73,8 +72,8 @@ gboolean _nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *password, GError **error) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Compiled without crypto support.")); return FALSE; } @@ -87,8 +86,8 @@ _nm_crypto_verify_pkcs8(const guint8 *data, GError **error) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Compiled without crypto support.")); return FALSE; } @@ -97,8 +96,8 @@ gboolean _nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_FAILED, _("Compiled without crypto support.")); return FALSE; } diff --git a/src/libnm-core-impl/nm-crypto.c b/src/libnm-crypto/nm-crypto.c index 78f793bd0b..69d2b53f9e 100644 --- a/src/libnm-core-impl/nm-crypto.c +++ b/src/libnm-crypto/nm-crypto.c @@ -4,7 +4,7 @@ * Copyright (C) 2007 - 2018 Red Hat, Inc. */ -#include "libnm-core-impl/nm-default-libnm-core.h" +#include "libnm-glib-aux/nm-default-glib-i18n-lib.h" #include "nm-crypto.h" @@ -16,8 +16,8 @@ #include "libnm-glib-aux/nm-io-utils.h" #include "nm-crypto-impl.h" -#include "nm-utils.h" -#include "nm-errors.h" + +/*****************************************************************************/ #define PEM_RSA_KEY_BEGIN "-----BEGIN RSA PRIVATE KEY-----" #define PEM_RSA_KEY_END "-----END RSA PRIVATE KEY-----" @@ -203,8 +203,8 @@ parse_old_openssl_key_file(const guint8 *data, end_tag = PEM_DSA_KEY_END; } else { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("PEM key file had no start tag")); return FALSE; } @@ -212,8 +212,8 @@ parse_old_openssl_key_file(const guint8 *data, start += strlen(start_tag); if (!find_tag(end_tag, data, data_len, start, &end)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("PEM key file had no end tag '%s'."), end_tag); return FALSE; @@ -240,8 +240,8 @@ parse_old_openssl_key_file(const guint8 *data, if (!strncmp(p, PROC_TYPE_TAG, strlen(PROC_TYPE_TAG))) { if (enc_tags++ != 0 || str_p != str) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Malformed PEM file: Proc-Type was not first tag.")); return FALSE; } @@ -249,8 +249,8 @@ parse_old_openssl_key_file(const guint8 *data, p += strlen(PROC_TYPE_TAG); if (strcmp(p, "4,ENCRYPTED")) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Malformed PEM file: unknown Proc-Type tag '%s'."), p); return FALSE; @@ -262,8 +262,8 @@ parse_old_openssl_key_file(const guint8 *data, if (enc_tags++ != 1 || str_p != str) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Malformed PEM file: DEK-Info was not the second tag.")); return FALSE; } @@ -274,8 +274,8 @@ parse_old_openssl_key_file(const guint8 *data, comma = strchr(p, ','); if (!comma || (*(comma + 1) == '\0')) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Malformed PEM file: no IV found in DEK-Info tag.")); return FALSE; } @@ -283,8 +283,8 @@ parse_old_openssl_key_file(const guint8 *data, comma++; if (!g_ascii_isxdigit(*comma)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Malformed PEM file: invalid format of IV in DEK-Info tag.")); return FALSE; } @@ -295,8 +295,8 @@ parse_old_openssl_key_file(const guint8 *data, cipher_info = nm_crypto_cipher_get_info_by_name(p, p_len); if (!cipher_info) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Malformed PEM file: unknown private key cipher '%s'."), p); return FALSE; @@ -305,8 +305,8 @@ parse_old_openssl_key_file(const guint8 *data, } else { if (enc_tags == 1) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, "Malformed PEM file: both Proc-Type and DEK-Info tags are required."); return FALSE; } @@ -318,8 +318,8 @@ parse_old_openssl_key_file(const guint8 *data, parsed.bin = (guint8 *) g_base64_decode(str, &parsed.len); if (!parsed.bin || parsed.len == 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Could not decode private key.")); nm_secret_ptr_clear(&parsed); return FALSE; @@ -360,8 +360,8 @@ parse_pkcs8_key_file(const guint8 *data, encrypted = FALSE; } else { g_set_error_literal(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Failed to find expected PKCS#8 start tag.")); return FALSE; } @@ -369,8 +369,8 @@ parse_pkcs8_key_file(const guint8 *data, start += strlen(start_tag); if (!find_tag(end_tag, data, data_len, start, &end)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Failed to find expected PKCS#8 end tag '%s'."), end_tag); return FALSE; @@ -382,8 +382,8 @@ parse_pkcs8_key_file(const guint8 *data, parsed->bin = (guint8 *) g_base64_decode(der_base64, &parsed->len); if (!parsed->bin || parsed->len == 0) { g_set_error_literal(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Failed to decode PKCS#8 private key.")); nm_secret_ptr_clear(parsed); return FALSE; @@ -412,8 +412,8 @@ parse_tpm2_wrapped_key_file(const guint8 *data, end_tag = PEM_TPM2_OLD_WRAPPED_KEY_END; } else { g_set_error_literal(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Failed to find expected TSS start tag.")); return FALSE; } @@ -421,8 +421,8 @@ parse_tpm2_wrapped_key_file(const guint8 *data, start += strlen(start_tag); if (!find_tag(end_tag, data, data_len, start, &end)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Failed to find expected TSS end tag '%s'."), end_tag); return FALSE; @@ -432,35 +432,6 @@ parse_tpm2_wrapped_key_file(const guint8 *data, return TRUE; } -static gboolean -file_read_contents(const char *filename, NMSecretPtr *out_contents, GError **error) -{ - nm_assert(out_contents); - nm_assert(out_contents->len == 0); - nm_assert(!out_contents->str); - - return nm_utils_file_get_contents(-1, - filename, - 100 * 1024 * 1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET, - &out_contents->str, - &out_contents->len, - NULL, - error); -} - -GBytes * -nm_crypto_read_file(const char *filename, GError **error) -{ - nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; - - g_return_val_if_fail(filename, NULL); - - if (!file_read_contents(filename, &contents, error)) - return NULL; - return nm_secret_copy_to_gbytes(contents.bin, contents.len); -} - /* * Convert a hex string into bytes. */ @@ -476,8 +447,8 @@ _nmtst_convert_iv(const char *src, gsize *out_len, GError **error) num = strlen(src); if (num == 0 || (num % 2) != 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("IV must be an even number of bytes in length.")); return NULL; } @@ -493,8 +464,8 @@ _nmtst_convert_iv(const char *src, gsize *out_len, GError **error) if (((c0 = nm_utils_hexchar_to_int(*(src++))) < 0) || ((c1 = nm_utils_hexchar_to_int(*(src++))) < 0)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("IV contains non-hexadecimal digits.")); nm_explicit_bzero(c, i); return FALSE; @@ -569,8 +540,8 @@ _nmtst_decrypt_key(NMCryptoCipherType cipher, if (bin_iv.len < 8) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("IV must contain at least 8 characters")); return FALSE; } @@ -619,8 +590,8 @@ nmtst_crypto_decrypt_openssl_private_key_data(const guint8 *data, if (!parse_old_openssl_key_file(data, data_len, &parsed, &key_type, &cipher, &iv, NULL)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Unable to determine private key type.")); return NULL; } @@ -632,8 +603,8 @@ nmtst_crypto_decrypt_openssl_private_key_data(const guint8 *data, if (cipher == NM_CRYPTO_CIPHER_UNKNOWN || !iv) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_PASSWORD, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_PASSWORD, _("Password provided, but key was not encrypted.")); return NULL; } @@ -661,7 +632,7 @@ nmtst_crypto_decrypt_openssl_private_key(const char *file, if (!_nm_crypto_init(error)) return NULL; - if (!file_read_contents(file, &contents, error)) + if (!nm_utils_read_crypto_file(file, &contents, error)) return NULL; return nmtst_crypto_decrypt_openssl_private_key_data(contents.bin, @@ -688,8 +659,8 @@ extract_pem_cert_data(const guint8 *contents, if (!find_tag(PEM_CERT_BEGIN, contents, contents_len, 0, &start)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("PEM certificate had no start tag '%s'."), PEM_CERT_BEGIN); return FALSE; @@ -698,8 +669,8 @@ extract_pem_cert_data(const guint8 *contents, start += strlen(PEM_CERT_BEGIN); if (!find_tag(PEM_CERT_END, contents, contents_len, start, &end)) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("PEM certificate had no end tag '%s'."), PEM_CERT_END); return FALSE; @@ -711,8 +682,8 @@ extract_pem_cert_data(const guint8 *contents, out_cert->bin = (guint8 *) g_base64_decode(der_base64, &out_cert->len); if (!out_cert->bin || !out_cert->len) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Failed to decode certificate.")); nm_secret_ptr_clear(out_cert); return FALSE; @@ -735,13 +706,13 @@ nm_crypto_load_and_verify_certificate(const char *file, if (!_nm_crypto_init(error)) goto out; - if (!file_read_contents(file, &contents, error)) + if (!nm_utils_read_crypto_file(file, &contents, error)) goto out; if (contents.len == 0) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Certificate file is empty")); goto out; } @@ -773,8 +744,8 @@ nm_crypto_load_and_verify_certificate(const char *file, } g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Failed to recognize certificate")); out: @@ -786,13 +757,13 @@ out: gboolean nm_crypto_is_pkcs12_data(const guint8 *data, gsize data_len, GError **error) { - GError *local = NULL; - gboolean success; + gs_free_error GError *local = NULL; + gboolean success; if (!data_len) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("Certificate file is empty")); return FALSE; } @@ -803,17 +774,14 @@ nm_crypto_is_pkcs12_data(const guint8 *data, gsize data_len, GError **error) return FALSE; success = _nm_crypto_verify_pkcs12(data, data_len, NULL, &local); - if (success == FALSE) { - /* If the error was just a decryption error, then it's pkcs#12 */ - if (local) { - if (g_error_matches(local, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED)) { - success = TRUE; - g_error_free(local); - } else - g_propagate_error(error, local); - } + + /* If the error was just a decryption error, then it's pkcs#12 */ + if (!success && !g_error_matches(local, _NM_CRYPTO_ERROR, _NM_CRYPTO_ERROR_DECRYPTION_FAILED)) { + g_propagate_error(error, g_steal_pointer(&local)); + return FALSE; } - return success; + + return TRUE; } gboolean @@ -826,7 +794,7 @@ nm_crypto_is_pkcs12_file(const char *file, GError **error) if (!_nm_crypto_init(error)) return FALSE; - if (!file_read_contents(file, &contents, error)) + if (!nm_utils_read_crypto_file(file, &contents, error)) return FALSE; return nm_crypto_is_pkcs12_data(contents.bin, contents.len, error); @@ -881,8 +849,8 @@ nm_crypto_verify_private_key_data(const guint8 *data, if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN && error && !*error) { g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, + _NM_CRYPTO_ERROR, + _NM_CRYPTO_ERROR_INVALID_DATA, _("not a valid private key")); } @@ -904,7 +872,7 @@ nm_crypto_verify_private_key(const char *filename, if (!_nm_crypto_init(error)) return NM_CRYPTO_FILE_FORMAT_UNKNOWN; - if (!file_read_contents(filename, &contents, error)) + if (!nm_utils_read_crypto_file(filename, &contents, error)) return NM_CRYPTO_FILE_FORMAT_UNKNOWN; return nm_crypto_verify_private_key_data(contents.bin, @@ -965,7 +933,7 @@ nmtst_crypto_rsa_key_encrypt(const guint8 *data, if (!nm_crypto_randomize(pw_buf.bin, pw_buf.len, error)) return NULL; - tmp_password = nm_utils_bin2hexstr(pw_buf.bin, pw_buf.len, -1); + tmp_password = _nm_utils_bin2hexstr(pw_buf.bin, pw_buf.len, -1); in_password = tmp_password; } @@ -1009,7 +977,7 @@ nmtst_crypto_rsa_key_encrypt(const guint8 *data, pem, g_strdup_printf("DEK-Info: %s,", nm_crypto_cipher_get_info(NM_CRYPTO_CIPHER_DES_EDE3_CBC)->name)); - g_ptr_array_add(pem, nm_utils_bin2hexstr(salt, sizeof(salt), sizeof(salt) * 2)); + g_ptr_array_add(pem, _nm_utils_bin2hexstr(salt, sizeof(salt), sizeof(salt) * 2)); g_ptr_array_add(pem, g_strdup("\n\n")); /* Convert the encrypted key to a base64 string */ @@ -1042,3 +1010,54 @@ nmtst_crypto_rsa_key_encrypt(const guint8 *data, NM_SET_OUT(out_password, g_strdup(tmp_password)); return nm_secret_buf_to_gbytes_take(ret, ret_len); } + +/*****************************************************************************/ + +static gboolean +file_has_extension(const char *filename, const char *extensions[]) +{ + const char *ext; + gsize i; + + ext = strrchr(filename, '.'); + if (!ext) + return FALSE; + + for (i = 0; extensions[i]; i++) { + if (!g_ascii_strcasecmp(ext, extensions[i])) + return TRUE; + } + + return FALSE; +} + +gboolean +nm_crypto_utils_file_is_certificate(const char *filename) +{ + const char *extensions[] = {".der", ".pem", ".crt", ".cer", NULL}; + NMCryptoFileFormat file_format; + + nm_assert(filename); + + if (!file_has_extension(filename, extensions)) + return FALSE; + + if (!nm_crypto_load_and_verify_certificate(filename, &file_format, NULL, NULL)) + return FALSE; + return file_format = NM_CRYPTO_FILE_FORMAT_X509; +} + +gboolean +nm_crypto_utils_file_is_private_key(const char *filename, gboolean *out_encrypted) +{ + const char *extensions[] = {".der", ".pem", ".p12", ".key", NULL}; + + nm_assert(filename); + + NM_SET_OUT(out_encrypted, FALSE); + if (!file_has_extension(filename, extensions)) + return FALSE; + + return nm_crypto_verify_private_key(filename, NULL, out_encrypted, NULL) + != NM_CRYPTO_FILE_FORMAT_UNKNOWN; +} diff --git a/src/libnm-core-impl/nm-crypto.h b/src/libnm-crypto/nm-crypto.h index a740c43c5b..48c7c6b7ab 100644 --- a/src/libnm-core-impl/nm-crypto.h +++ b/src/libnm-crypto/nm-crypto.h @@ -93,4 +93,7 @@ guint8 *nmtst_crypto_make_des_aes_key(NMCryptoCipherType cipher, /*****************************************************************************/ +gboolean nm_crypto_utils_file_is_certificate(const char *filename); +gboolean nm_crypto_utils_file_is_private_key(const char *filename, gboolean *out_encrypted); + #endif /* __NM_CRYPTO_H__ */ diff --git a/src/libnm-glib-aux/nm-secret-utils.c b/src/libnm-glib-aux/nm-secret-utils.c index c764b6e575..983b04cac8 100644 --- a/src/libnm-glib-aux/nm-secret-utils.c +++ b/src/libnm-glib-aux/nm-secret-utils.c @@ -10,6 +10,8 @@ #include <malloc.h> +#include "nm-io-utils.h" + /*****************************************************************************/ void @@ -176,3 +178,34 @@ nm_utils_memeqzero_secret(gconstpointer data, gsize length) } return 1 & ((acc - 1) >> 8); } + +/*****************************************************************************/ + +gboolean +nm_utils_read_crypto_file(const char *filename, NMSecretPtr *out_contents, GError **error) +{ + nm_assert(out_contents); + nm_assert(out_contents->len == 0); + nm_assert(!out_contents->str); + + return nm_utils_file_get_contents(-1, + filename, + 100 * 1024 * 1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET, + &out_contents->str, + &out_contents->len, + NULL, + error); +} + +GBytes * +nm_utils_read_crypto_file_to_bytes(const char *filename, GError **error) +{ + nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; + + g_return_val_if_fail(filename, NULL); + + if (!nm_utils_read_crypto_file(filename, &contents, error)) + return NULL; + return nm_secret_copy_to_gbytes(contents.bin, contents.len); +} diff --git a/src/libnm-glib-aux/nm-secret-utils.h b/src/libnm-glib-aux/nm-secret-utils.h index 513dbca5bc..c175bc8f3e 100644 --- a/src/libnm-glib-aux/nm-secret-utils.h +++ b/src/libnm-glib-aux/nm-secret-utils.h @@ -286,4 +286,8 @@ nm_secret_mem_try_realloc_take(gpointer m_old, gboolean do_bzero_mem, gsize cur_ /*****************************************************************************/ +gboolean nm_utils_read_crypto_file(const char *filename, NMSecretPtr *out_contents, GError **error); + +GBytes *nm_utils_read_crypto_file_to_bytes(const char *filename, GError **error); + #endif /* __NM_SECRET_UTILS_H__ */ diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c index 3b5bc6f92b..7c93615ed8 100644 --- a/src/libnm-glib-aux/nm-shared-utils.c +++ b/src/libnm-glib-aux/nm-shared-utils.c @@ -4851,6 +4851,27 @@ nm_utils_bin2hexstr_full(gconstpointer addr, return out0; } +char * +_nm_utils_bin2hexstr(gconstpointer src, gsize len, int final_len) +{ + char *result; + gsize buflen = (len * 2) + 1; + + nm_assert(src); + nm_assert(len > 0 && (buflen - 1) / 2 == len); + nm_assert(final_len < 0 || (gsize) final_len < buflen); + + result = g_malloc(buflen); + + nm_utils_bin2hexstr_full(src, len, '\0', FALSE, result); + + /* Cut converted key off at the correct length for this cipher type */ + if (final_len >= 0 && (gsize) final_len < buflen) + result[final_len] = '\0'; + + return result; +} + guint8 * nm_utils_hexstr2bin_full(const char *hexstr, gboolean allow_0x_prefix, diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h index 6070bb0e0c..d0c7434b3c 100644 --- a/src/libnm-glib-aux/nm-shared-utils.h +++ b/src/libnm-glib-aux/nm-shared-utils.h @@ -2710,6 +2710,8 @@ char *nm_utils_bin2hexstr_full(gconstpointer addr, gboolean upper_case, char *out); +char *_nm_utils_bin2hexstr(gconstpointer src, gsize len, int final_len); + #define nm_utils_bin2hexstr_a(addr, length, delimiter, upper_case, str_to_free) \ ({ \ gconstpointer _addr = (addr); \ diff --git a/src/meson.build b/src/meson.build index ab69691566..f3c87f1af3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -78,6 +78,7 @@ subdir('libnm-systemd-core') subdir('libnm-udev-aux') subdir('libnm-base') subdir('libnm-platform') +subdir('libnm-crypto') subdir('libnm-core-public') subdir('libnm-core-intern') subdir('libnm-core-aux-intern') |