From 98da2ae72c1a81373d56d46c4a389e4a359a4fd6 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 30 Oct 2014 10:19:32 -0400 Subject: [PATCH 1/4] libnm-core: port test-crypto to g_assert* macros And in particular, add some g_assert_error() checks --- libnm-core/tests/test-crypto.c | 193 +++++++++++++-------------------- 1 file changed, 77 insertions(+), 116 deletions(-) diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c index a61042e664..b7a2b87bf8 100644 --- a/libnm-core/tests/test-crypto.c +++ b/libnm-core/tests/test-crypto.c @@ -32,6 +32,7 @@ #include "crypto.h" #include "nm-utils.h" +#include "nm-errors.h" #include "nm-test-utils.h" @@ -104,13 +105,8 @@ test_cert (gconstpointer test_data) path = g_build_filename (TEST_CERT_DIR, (const char *) test_data, NULL); array = crypto_load_and_verify_certificate (path, &format, &error); - ASSERT (array != NULL, "cert", - "couldn't read certificate file '%s': %d %s", - path, error->code, error->message); - - ASSERT (format == NM_CRYPTO_FILE_FORMAT_X509, "cert", - "%s: unexpected certificate format (expected %d, got %d)", - path, NM_CRYPTO_FILE_FORMAT_X509, format); + g_assert_no_error (error); + g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_X509); g_byte_array_free (array, TRUE); } @@ -135,50 +131,37 @@ static void test_load_private_key (const char *path, const char *password, const char *decrypted_path, - gboolean expect_fail, - const char *desc) + int expected_error) { NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; GByteArray *array, *decrypted; GError *error = NULL; array = crypto_decrypt_private_key (path, password, &key_type, &error); - if (expect_fail) { - ASSERT (array == NULL, desc, - "unexpected success reading private key file '%s' with " - "invalid password", - path); + /* Even if the password is wrong, we should determine the key type */ + g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); - ASSERT (key_type != NM_CRYPTO_KEY_TYPE_UNKNOWN, desc, - "unexpected failure determining private key file '%s' " - "type with invalid password (expected %d, got %d)", - path, NM_CRYPTO_KEY_TYPE_UNKNOWN, key_type); + if (expected_error != -1) { + g_assert (array == NULL); + g_assert_error (error, NM_CRYPTO_ERROR, expected_error); + g_clear_error (&error); return; } - ASSERT (array != NULL, desc, - "couldn't read private key file '%s': %d %s", - path, error->code, error->message); + if (password == NULL) { + g_assert (array == NULL); + g_assert_no_error (error); + return; + } - ASSERT (key_type == NM_CRYPTO_KEY_TYPE_RSA, desc, - "%s: unexpected private key type (expected %d, got %d)", - path, NM_CRYPTO_KEY_TYPE_RSA, key_type); + g_assert (array != NULL); if (decrypted_path) { /* Compare the crypto decrypted key against a known-good decryption */ decrypted = file_to_byte_array (decrypted_path); - ASSERT (decrypted != NULL, desc, - "couldn't read decrypted private key file '%s': %d %s", - decrypted_path, error->code, error->message); - - ASSERT (decrypted->len > 0, desc, "decrypted key file invalid (size 0)"); - - ASSERT (decrypted->len == array->len, - desc, "decrypted key file (%d) and decrypted key data (%d) lengths don't match", - decrypted->len, array->len); - - ASSERT (memcmp (decrypted->data, array->data, array->len) == 0, - desc, "decrypted key file and decrypted key data don't match"); + g_assert (decrypted != NULL); + g_assert (decrypted->len == array->len); + g_assert (memcmp (decrypted->data, array->data, array->len) == 0); g_byte_array_free (decrypted, TRUE); } @@ -189,75 +172,68 @@ test_load_private_key (const char *path, static void test_load_pkcs12 (const char *path, const char *password, - gboolean expect_fail, - const char *desc) + int expected_error) { NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; GError *error = NULL; format = crypto_verify_private_key (path, password, &error); - if (expect_fail) { - ASSERT (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN, desc, - "unexpected success reading PKCS#12 private key file " - "'%s' with invalid password", - path); + if (expected_error != -1) { + g_assert_error (error, NM_CRYPTO_ERROR, expected_error); + g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + g_clear_error (&error); } else { - ASSERT (format == NM_CRYPTO_FILE_FORMAT_PKCS12, desc, - "%s: unexpected PKCS#12 private key file format (expected %d, got " - "%d): %d %s", - path, NM_CRYPTO_FILE_FORMAT_PKCS12, format, error->code, error->message); + g_assert_no_error (error); + g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12); } } static void -test_load_pkcs12_no_password (const char *path, const char *desc) +test_load_pkcs12_no_password (const char *path) { NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; GError *error = NULL; /* We should still get a valid returned crypto file format */ format = crypto_verify_private_key (path, NULL, &error); - ASSERT (format == NM_CRYPTO_FILE_FORMAT_PKCS12, desc, - "%s: unexpected PKCS#12 private key file format (expected %d, got " - "%d): %d %s", - path, NM_CRYPTO_FILE_FORMAT_PKCS12, format, error->code, error->message); + g_assert_no_error (error); + g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12); } static void -test_is_pkcs12 (const char *path, gboolean expect_fail, const char *desc) +test_is_pkcs12 (const char *path, gboolean expect_fail) { gboolean is_pkcs12; + GError *error = NULL; - is_pkcs12 = crypto_is_pkcs12_file (path, NULL); - if (expect_fail) { - ASSERT (is_pkcs12 == FALSE, desc, - "unexpected success reading non-PKCS#12 file '%s'", - path); - } else { - ASSERT (is_pkcs12 == TRUE, desc, "couldn't read PKCS#12 file '%s'", path); - } + is_pkcs12 = crypto_is_pkcs12_file (path, &error); + /* crypto_is_pkcs12_file() only returns an error if it couldn't read the + * file, which we don't expect to happen here. + */ + g_assert_no_error (error); + + if (expect_fail) + g_assert (!is_pkcs12); + else + g_assert (is_pkcs12); } static void test_load_pkcs8 (const char *path, const char *password, - gboolean expect_fail, - const char *desc) + int expected_error) { NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; GError *error = NULL; format = crypto_verify_private_key (path, password, &error); - if (expect_fail) { - ASSERT (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN, desc, - "unexpected success reading PKCS#8 private key file " - "'%s' with invalid password", - path); + if (expected_error != -1) { + g_assert_error (error, NM_CRYPTO_ERROR, expected_error); + g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + g_clear_error (&error); } else { - ASSERT (format == NM_CRYPTO_FILE_FORMAT_RAW_KEY, desc, - "%s: unexpected PKCS#8 private key file format (expected %d, got " - "%d): %d %s", - path, NM_CRYPTO_FILE_FORMAT_RAW_KEY, format, error->code, error->message); + g_assert_no_error (error); + g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_RAW_KEY); } } @@ -285,51 +261,36 @@ is_cipher_aes (const char *path) static void test_encrypt_private_key (const char *path, - const char *password, - const char *desc) + const char *password) { NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; GByteArray *array, *encrypted, *re_decrypted; GError *error = NULL; array = crypto_decrypt_private_key (path, password, &key_type, &error); - ASSERT (array != NULL, desc, - "couldn't read private key file '%s': %d %s", - path, error->code, error->message); - - ASSERT (key_type == NM_CRYPTO_KEY_TYPE_RSA, desc, - "%s: unexpected private key type (expected %d, got %d)", - path, NM_CRYPTO_KEY_TYPE_RSA, key_type); + g_assert_no_error (error); + g_assert (array != NULL); + g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); /* Now re-encrypt the private key */ if (is_cipher_aes (path)) encrypted = nm_utils_rsa_key_encrypt_aes (array->data, array->len, password, NULL, &error); else encrypted = nm_utils_rsa_key_encrypt (array->data, array->len, password, NULL, &error); - ASSERT (encrypted != NULL, desc, - "couldn't re-encrypt private key file '%s': %d %s", - path, error->code, error->message); + g_assert_no_error (error); + g_assert (encrypted != NULL); /* Then re-decrypt the private key */ key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; re_decrypted = crypto_decrypt_private_key_data (encrypted->data, encrypted->len, password, &key_type, &error); - ASSERT (re_decrypted != NULL, desc, - "couldn't read private key file '%s': %d %s", - path, error->code, error->message); - - ASSERT (key_type == NM_CRYPTO_KEY_TYPE_RSA, desc, - "%s: unexpected private key type (expected %d, got %d)", - path, NM_CRYPTO_KEY_TYPE_RSA, key_type); + g_assert_no_error (error); + g_assert (re_decrypted != NULL); + g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); /* Compare the original decrypted key with the re-decrypted key */ - ASSERT (array->len == re_decrypted->len, desc, - "%s: unexpected re-decrypted private key length (expected %d, got %d)", - path, array->len, re_decrypted->len); - - ASSERT (!memcmp (array->data, re_decrypted->data, array->len), desc, - "%s: unexpected private key data", - path); + g_assert_cmpint (array->len, ==, re_decrypted->len); + g_assert (!memcmp (array->data, re_decrypted->data, array->len)); g_byte_array_free (re_decrypted, TRUE); g_byte_array_free (encrypted, TRUE); @@ -344,18 +305,18 @@ test_key (gconstpointer test_data) parts = g_strsplit ((const char *) test_data, ", ", -1); len = g_strv_length (parts); - ASSERT (len == 2 || len == 3, "test-crypto", - "wrong number of arguments (, , [])"); + if (len != 2 && len != 3) + g_error ("wrong number of arguments (, , [])"); path = g_build_filename (TEST_CERT_DIR, parts[0], NULL); password = parts[1]; decrypted_path = parts[2] ? g_build_filename (TEST_CERT_DIR, parts[2], NULL) : NULL; - test_is_pkcs12 (path, TRUE, "not-pkcs12"); - test_load_private_key (path, password, decrypted_path, FALSE, "private-key"); - test_load_private_key (path, "blahblahblah", NULL, TRUE, "private-key-bad-password"); - test_load_private_key (path, NULL, NULL, TRUE, "private-key-no-password"); - test_encrypt_private_key (path, password, "private-key-rencrypt"); + test_is_pkcs12 (path, TRUE); + test_load_private_key (path, password, decrypted_path, -1); + test_load_private_key (path, "blahblahblah", NULL, NM_CRYPTO_ERROR_DECRYPTION_FAILED); + test_load_private_key (path, NULL, NULL, -1); + test_encrypt_private_key (path, password); g_free (path); g_free (decrypted_path); @@ -368,16 +329,16 @@ test_pkcs12 (gconstpointer test_data) char **parts, *path, *password; parts = g_strsplit ((const char *) test_data, ", ", -1); - ASSERT (g_strv_length (parts) == 2, "test-crypto", - "wrong number of arguments (, )"); + if (g_strv_length (parts) != 2) + g_error ("wrong number of arguments (, )"); path = g_build_filename (TEST_CERT_DIR, parts[0], NULL); password = parts[1]; - test_is_pkcs12 (path, FALSE, "is-pkcs12"); - test_load_pkcs12 (path, password, FALSE, "pkcs12-private-key"); - test_load_pkcs12 (path, "blahblahblah", TRUE, "pkcs12-private-key-bad-password"); - test_load_pkcs12_no_password (path, "pkcs12-private-key-no-password"); + test_is_pkcs12 (path, FALSE); + test_load_pkcs12 (path, password, -1); + test_load_pkcs12 (path, "blahblahblah", NM_CRYPTO_ERROR_DECRYPTION_FAILED); + test_load_pkcs12_no_password (path); g_free (path); g_strfreev (parts); @@ -389,19 +350,19 @@ test_pkcs8 (gconstpointer test_data) char **parts, *path, *password; parts = g_strsplit ((const char *) test_data, ", ", -1); - ASSERT (g_strv_length (parts) == 2, "test-crypto", - "wrong number of arguments (, )"); + if (g_strv_length (parts) != 2) + g_error ("wrong number of arguments (, )"); path = g_build_filename (TEST_CERT_DIR, parts[0], NULL); password = parts[1]; - test_is_pkcs12 (path, TRUE, "not-pkcs12"); - test_load_pkcs8 (path, password, FALSE, "pkcs8-private-key"); + test_is_pkcs12 (path, TRUE); + test_load_pkcs8 (path, password, -1); /* Until gnutls and NSS grow support for all the ciphers that openssl * can use with PKCS#8, we can't actually verify the password. So we * expect a bad password to work for the time being. */ - test_load_pkcs8 (path, "blahblahblah", FALSE, "pkcs8-private-key-bad-password"); + test_load_pkcs8 (path, "blahblahblah", -1); g_free (path); g_strfreev (parts); From 131365882955e3e2e036a8bf04b341469fcb32a9 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 30 Oct 2014 11:07:03 -0400 Subject: [PATCH 2/4] libnm-core, libnm-util: move test cert files to libnm-core/ Move the certificate files used by the libnm-util and libnm-core tests from libnm-util/tests/certs/ to libnm-core/tests/certs/. --- configure.ac | 1 - libnm-core/tests/Makefile.am | 28 +++++++++++++++++- .../tests/certs/ca-no-ending-newline.pem | 0 .../tests/certs/pkcs8-decrypted.der | Bin .../tests/certs/pkcs8-enc-key.pem | 0 .../tests/certs/pkcs8-noenc-key.pem | 0 .../tests/certs/test-aes-key.pem | 0 .../tests/certs/test-cert.p12 | Bin .../tests/certs/test-key-only-decrypted.der | Bin .../tests/certs/test-key-only.pem | 0 .../tests/certs/test2-cert.p12 | Bin .../tests/certs/test2_ca_cert.pem | 0 .../tests/certs/test2_key_and_cert.pem | 0 .../tests/certs/test_ca_cert.der | Bin .../tests/certs/test_ca_cert.pem | 0 .../tests/certs/test_key_and_cert.pem | 0 libnm-util/tests/Makefile.am | 4 +-- libnm-util/tests/certs/Makefile.am | 25 ---------------- 18 files changed, 28 insertions(+), 30 deletions(-) rename {libnm-util => libnm-core}/tests/certs/ca-no-ending-newline.pem (100%) rename {libnm-util => libnm-core}/tests/certs/pkcs8-decrypted.der (100%) rename {libnm-util => libnm-core}/tests/certs/pkcs8-enc-key.pem (100%) rename {libnm-util => libnm-core}/tests/certs/pkcs8-noenc-key.pem (100%) rename {libnm-util => libnm-core}/tests/certs/test-aes-key.pem (100%) rename {libnm-util => libnm-core}/tests/certs/test-cert.p12 (100%) rename {libnm-util => libnm-core}/tests/certs/test-key-only-decrypted.der (100%) rename {libnm-util => libnm-core}/tests/certs/test-key-only.pem (100%) rename {libnm-util => libnm-core}/tests/certs/test2-cert.p12 (100%) rename {libnm-util => libnm-core}/tests/certs/test2_ca_cert.pem (100%) rename {libnm-util => libnm-core}/tests/certs/test2_key_and_cert.pem (100%) rename {libnm-util => libnm-core}/tests/certs/test_ca_cert.der (100%) rename {libnm-util => libnm-core}/tests/certs/test_ca_cert.pem (100%) rename {libnm-util => libnm-core}/tests/certs/test_key_and_cert.pem (100%) delete mode 100644 libnm-util/tests/certs/Makefile.am diff --git a/configure.ac b/configure.ac index c123fe854a..afc55defa1 100644 --- a/configure.ac +++ b/configure.ac @@ -953,7 +953,6 @@ libnm-util/libnm-util.pc libnm-util/nm-version.h libnm-util/Makefile libnm-util/tests/Makefile -libnm-util/tests/certs/Makefile libnm-glib/libnm-glib.pc libnm-glib/libnm-glib-vpn.pc libnm-glib/Makefile diff --git a/libnm-core/tests/Makefile.am b/libnm-core/tests/Makefile.am index eea0fc198e..dc8c40080b 100644 --- a/libnm-core/tests/Makefile.am +++ b/libnm-core/tests/Makefile.am @@ -1,6 +1,6 @@ if ENABLE_TESTS -certsdir = $(top_srcdir)/libnm-util/tests/certs +certsdir = $(srcdir)/certs AM_CPPFLAGS = \ -I${top_srcdir}/include \ @@ -27,3 +27,29 @@ LDADD = \ TESTS = $(noinst_PROGRAMS) endif + +# test-cert.p12 created with: +# +# openssl pkcs12 -export \ +# -in test_key_and_cert.pem \ +# -inkey test_key_and_cert.pem \ +# -certfile test_ca_cert.pem \ +# -name "test-pkcs12" \ +# -out test-cert.p12 + +EXTRA_DIST = \ + certs/test_ca_cert.pem \ + certs/test_ca_cert.der \ + certs/test_key_and_cert.pem \ + certs/test-cert.p12 \ + certs/test2_ca_cert.pem \ + certs/test2_key_and_cert.pem \ + certs/test2-cert.p12 \ + certs/ca-no-ending-newline.pem \ + certs/test-key-only.pem \ + certs/test-key-only-decrypted.der \ + certs/pkcs8-enc-key.pem \ + certs/pkcs8-noenc-key.pem \ + certs/pkcs8-decrypted.der \ + certs/test-aes-key.pem + diff --git a/libnm-util/tests/certs/ca-no-ending-newline.pem b/libnm-core/tests/certs/ca-no-ending-newline.pem similarity index 100% rename from libnm-util/tests/certs/ca-no-ending-newline.pem rename to libnm-core/tests/certs/ca-no-ending-newline.pem diff --git a/libnm-util/tests/certs/pkcs8-decrypted.der b/libnm-core/tests/certs/pkcs8-decrypted.der similarity index 100% rename from libnm-util/tests/certs/pkcs8-decrypted.der rename to libnm-core/tests/certs/pkcs8-decrypted.der diff --git a/libnm-util/tests/certs/pkcs8-enc-key.pem b/libnm-core/tests/certs/pkcs8-enc-key.pem similarity index 100% rename from libnm-util/tests/certs/pkcs8-enc-key.pem rename to libnm-core/tests/certs/pkcs8-enc-key.pem diff --git a/libnm-util/tests/certs/pkcs8-noenc-key.pem b/libnm-core/tests/certs/pkcs8-noenc-key.pem similarity index 100% rename from libnm-util/tests/certs/pkcs8-noenc-key.pem rename to libnm-core/tests/certs/pkcs8-noenc-key.pem diff --git a/libnm-util/tests/certs/test-aes-key.pem b/libnm-core/tests/certs/test-aes-key.pem similarity index 100% rename from libnm-util/tests/certs/test-aes-key.pem rename to libnm-core/tests/certs/test-aes-key.pem diff --git a/libnm-util/tests/certs/test-cert.p12 b/libnm-core/tests/certs/test-cert.p12 similarity index 100% rename from libnm-util/tests/certs/test-cert.p12 rename to libnm-core/tests/certs/test-cert.p12 diff --git a/libnm-util/tests/certs/test-key-only-decrypted.der b/libnm-core/tests/certs/test-key-only-decrypted.der similarity index 100% rename from libnm-util/tests/certs/test-key-only-decrypted.der rename to libnm-core/tests/certs/test-key-only-decrypted.der diff --git a/libnm-util/tests/certs/test-key-only.pem b/libnm-core/tests/certs/test-key-only.pem similarity index 100% rename from libnm-util/tests/certs/test-key-only.pem rename to libnm-core/tests/certs/test-key-only.pem diff --git a/libnm-util/tests/certs/test2-cert.p12 b/libnm-core/tests/certs/test2-cert.p12 similarity index 100% rename from libnm-util/tests/certs/test2-cert.p12 rename to libnm-core/tests/certs/test2-cert.p12 diff --git a/libnm-util/tests/certs/test2_ca_cert.pem b/libnm-core/tests/certs/test2_ca_cert.pem similarity index 100% rename from libnm-util/tests/certs/test2_ca_cert.pem rename to libnm-core/tests/certs/test2_ca_cert.pem diff --git a/libnm-util/tests/certs/test2_key_and_cert.pem b/libnm-core/tests/certs/test2_key_and_cert.pem similarity index 100% rename from libnm-util/tests/certs/test2_key_and_cert.pem rename to libnm-core/tests/certs/test2_key_and_cert.pem diff --git a/libnm-util/tests/certs/test_ca_cert.der b/libnm-core/tests/certs/test_ca_cert.der similarity index 100% rename from libnm-util/tests/certs/test_ca_cert.der rename to libnm-core/tests/certs/test_ca_cert.der diff --git a/libnm-util/tests/certs/test_ca_cert.pem b/libnm-core/tests/certs/test_ca_cert.pem similarity index 100% rename from libnm-util/tests/certs/test_ca_cert.pem rename to libnm-core/tests/certs/test_ca_cert.pem diff --git a/libnm-util/tests/certs/test_key_and_cert.pem b/libnm-core/tests/certs/test_key_and_cert.pem similarity index 100% rename from libnm-util/tests/certs/test_key_and_cert.pem rename to libnm-core/tests/certs/test_key_and_cert.pem diff --git a/libnm-util/tests/Makefile.am b/libnm-util/tests/Makefile.am index 6d11d0dd16..690bdbf65a 100644 --- a/libnm-util/tests/Makefile.am +++ b/libnm-util/tests/Makefile.am @@ -1,7 +1,5 @@ if ENABLE_TESTS -SUBDIRS=certs - AM_CPPFLAGS = \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libnm-util \ @@ -10,7 +8,7 @@ AM_CPPFLAGS = \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ -DBUILD_DIR=\"$(abs_builddir)\" \ - -DTEST_CERT_DIR=\"$(top_srcdir)/libnm-util/tests/certs/\" + -DTEST_CERT_DIR=\"$(top_srcdir)/libnm-core/tests/certs/\" TESTS = \ test-settings-defaults \ diff --git a/libnm-util/tests/certs/Makefile.am b/libnm-util/tests/certs/Makefile.am deleted file mode 100644 index 309925174c..0000000000 --- a/libnm-util/tests/certs/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -# test-cert.p12 created with: -# -# openssl pkcs12 -export \ -# -in test_key_and_cert.pem \ -# -inkey test_key_and_cert.pem \ -# -certfile test_ca_cert.pem \ -# -name "test-pkcs12" \ -# -out test-cert.p12 - -EXTRA_DIST = \ - test_ca_cert.pem \ - test_ca_cert.der \ - test_key_and_cert.pem \ - test-cert.p12 \ - test2_ca_cert.pem \ - test2_key_and_cert.pem \ - test2-cert.p12 \ - ca-no-ending-newline.pem \ - test-key-only.pem \ - test-key-only-decrypted.der \ - pkcs8-enc-key.pem \ - pkcs8-noenc-key.pem \ - pkcs8-decrypted.der \ - test-aes-key.pem - From 7c74e71e9133f3d9c5d55cf7156340d0f7857e3a Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 1 Nov 2014 12:16:17 -0400 Subject: [PATCH 3/4] libnm-core: tweak crypto.c APIs Update crypto_verify_private_key() and crypto_verify_private_key_data() to indicate whether the key was encrypted or not. Rename crypto_decrypt_private_key() and crypto_decrypt_private_key_data() to crypto_decrypt_openssl_private_key*, since that's the only private key format they deal with, and the old names made them sound more generic than they were. Also, update the openssl private key parsing code to recognize unencrypted private keys as well. (Previously we accepted unencrypted PKCS#8 keys, but not unencrypted openssl-style keys.) --- libnm-core/crypto.c | 119 +++++++++++++++++---------------- libnm-core/crypto.h | 20 +++--- libnm-core/nm-setting-8021x.c | 8 +-- libnm-core/tests/Makefile.am | 1 + libnm-core/tests/test-crypto.c | 20 ++++-- 5 files changed, 91 insertions(+), 77 deletions(-) diff --git a/libnm-core/crypto.c b/libnm-core/crypto.c index e54d101e48..592f4e41b5 100644 --- a/libnm-core/crypto.c +++ b/libnm-core/crypto.c @@ -78,7 +78,7 @@ find_tag (const char *tag, static GByteArray * parse_old_openssl_key_file (const guint8 *data, gsize data_len, - int key_type, + NMCryptoKeyType *out_key_type, char **out_cipher, char **out_iv, GError **error) @@ -89,6 +89,7 @@ parse_old_openssl_key_file (const guint8 *data, gsize start = 0, end = 0; GString *str = NULL; int enc_tags = 0; + NMCryptoKeyType key_type; char *iv = NULL; char *cipher = NULL; unsigned char *tmp = NULL; @@ -97,20 +98,19 @@ parse_old_openssl_key_file (const guint8 *data, const char *end_tag; guint8 save_end = 0; - switch (key_type) { - case NM_CRYPTO_KEY_TYPE_RSA: + *out_key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + *out_iv = NULL; + *out_cipher = NULL; + + if (find_tag (PEM_RSA_KEY_BEGIN, data, data_len, 0, &start)) { + key_type = NM_CRYPTO_KEY_TYPE_RSA; start_tag = PEM_RSA_KEY_BEGIN; end_tag = PEM_RSA_KEY_END; - break; - case NM_CRYPTO_KEY_TYPE_DSA: + } else if (find_tag (PEM_DSA_KEY_BEGIN, data, data_len, 0, &start)) { + key_type = NM_CRYPTO_KEY_TYPE_DSA; start_tag = PEM_DSA_KEY_BEGIN; end_tag = PEM_DSA_KEY_END; - break; - default: - g_assert_not_reached (); - } - - if (!find_tag (start_tag, data, data_len, 0, &start)) + } else goto parse_error; start += strlen (start_tag); @@ -144,7 +144,7 @@ parse_old_openssl_key_file (const guint8 *data, continue; if (!strncmp (p, PROC_TYPE_TAG, strlen (PROC_TYPE_TAG))) { - if (enc_tags++ != 0) { + if (enc_tags++ != 0 || str->len != 0) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Malformed PEM file: Proc-Type was not first tag.")); @@ -162,7 +162,7 @@ parse_old_openssl_key_file (const guint8 *data, } else if (!strncmp (p, DEK_INFO_TAG, strlen (DEK_INFO_TAG))) { char *comma; - if (enc_tags++ != 1) { + if (enc_tags++ != 1 || str->len != 0) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Malformed PEM file: DEK-Info was not the second tag.")); @@ -203,7 +203,7 @@ parse_old_openssl_key_file (const guint8 *data, goto parse_error; } } else { - if ((enc_tags != 0) && (enc_tags != 2)) { + if (enc_tags == 1) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, "Malformed PEM file: both Proc-Type and DEK-Info tags are required."); @@ -229,6 +229,7 @@ parse_old_openssl_key_file (const guint8 *data, g_byte_array_append (bindata, tmp, tmp_len); g_free (tmp); + *out_key_type = key_type; *out_iv = iv; *out_cipher = cipher; return bindata; @@ -475,14 +476,14 @@ out: } GByteArray * -crypto_decrypt_private_key_data (const guint8 *data, - gsize data_len, - const char *password, - NMCryptoKeyType *out_key_type, - GError **error) +crypto_decrypt_openssl_private_key_data (const guint8 *data, + gsize data_len, + const char *password, + NMCryptoKeyType *out_key_type, + GError **error) { GByteArray *decrypted = NULL; - NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_RSA; + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; GByteArray *parsed; char *iv = NULL; char *cipher = NULL; @@ -491,30 +492,24 @@ crypto_decrypt_private_key_data (const guint8 *data, if (out_key_type) g_return_val_if_fail (*out_key_type == NM_CRYPTO_KEY_TYPE_UNKNOWN, NULL); - /* OpenSSL non-standard legacy PEM files */ + parsed = parse_old_openssl_key_file (data, data_len, &key_type, &cipher, &iv, NULL); + /* return the key type even if decryption failed */ + if (out_key_type) + *out_key_type = key_type; - /* Try RSA keys first */ - parsed = parse_old_openssl_key_file (data, data_len, key_type, &cipher, &iv, error); if (!parsed) { - g_clear_error (error); - - /* DSA next */ - key_type = NM_CRYPTO_KEY_TYPE_DSA; - parsed = parse_old_openssl_key_file (data, data_len, key_type, &cipher, &iv, error); - if (!parsed) { - g_clear_error (error); - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Unable to determine private key type.")); - } + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Unable to determine private key type.")); + return NULL; } - if (parsed) { - /* return the key type even if decryption failed */ - if (out_key_type) - *out_key_type = key_type; - - if (password) { + if (password) { + if (!cipher || !iv) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_PASSWORD, + _("Password provided, but key was not encrypted.")); + } else { decrypted = decrypt_key (cipher, key_type, parsed->data, @@ -523,9 +518,10 @@ crypto_decrypt_private_key_data (const guint8 *data, password, error); } - g_byte_array_free (parsed, TRUE); - } + } else if (!cipher && !iv) + decrypted = g_byte_array_ref (parsed); + g_byte_array_unref (parsed); g_free (cipher); g_free (iv); @@ -533,18 +529,18 @@ crypto_decrypt_private_key_data (const guint8 *data, } GByteArray * -crypto_decrypt_private_key (const char *file, - const char *password, - NMCryptoKeyType *out_key_type, - GError **error) +crypto_decrypt_openssl_private_key (const char *file, + const char *password, + NMCryptoKeyType *out_key_type, + GError **error) { GByteArray *contents; GByteArray *key = NULL; contents = file_to_g_byte_array (file, error); if (contents) { - key = crypto_decrypt_private_key_data (contents->data, contents->len, - password, out_key_type, error); + key = crypto_decrypt_openssl_private_key_data (contents->data, contents->len, + password, out_key_type, error); g_byte_array_free (contents, TRUE); } return key; @@ -684,6 +680,7 @@ NMCryptoFileFormat crypto_verify_private_key_data (const guint8 *data, gsize data_len, const char *password, + gboolean *out_is_encrypted, GError **error) { GByteArray *tmp; @@ -691,42 +688,50 @@ crypto_verify_private_key_data (const guint8 *data, NMCryptoKeyType ktype = NM_CRYPTO_KEY_TYPE_UNKNOWN; gboolean is_encrypted = FALSE; - g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (data != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + g_return_val_if_fail (out_is_encrypted == NULL || *out_is_encrypted == FALSE, NM_CRYPTO_FILE_FORMAT_UNKNOWN); /* Check for PKCS#12 first */ if (crypto_is_pkcs12_data (data, data_len)) { + is_encrypted = TRUE; if (!password || crypto_verify_pkcs12 (data, data_len, password, error)) format = NM_CRYPTO_FILE_FORMAT_PKCS12; } else { /* Maybe it's PKCS#8 */ - tmp = parse_pkcs8_key_file (data, data_len, &is_encrypted, error); + tmp = parse_pkcs8_key_file (data, data_len, &is_encrypted, NULL); if (tmp) { if (crypto_verify_pkcs8 (tmp->data, tmp->len, is_encrypted, password, error)) format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; } else { - g_clear_error (error); + char *cipher, *iv; /* Or it's old-style OpenSSL */ - tmp = crypto_decrypt_private_key_data (data, data_len, password, &ktype, error); - if (tmp) - format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; - else if (!password && (ktype != NM_CRYPTO_KEY_TYPE_UNKNOWN)) + tmp = parse_old_openssl_key_file (data, data_len, &ktype, + &cipher, &iv, NULL); + if (tmp) { format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; + is_encrypted = (cipher && iv); + g_free (cipher); + g_free (iv); + } } if (tmp) { - /* Don't leave decrypted key data around */ + /* Don't leave key data around */ memset (tmp->data, 0, tmp->len); g_byte_array_free (tmp, TRUE); } } + if (out_is_encrypted) + *out_is_encrypted = is_encrypted; return format; } NMCryptoFileFormat crypto_verify_private_key (const char *filename, const char *password, + gboolean *out_is_encrypted, GError **error) { GByteArray *contents; @@ -736,7 +741,7 @@ crypto_verify_private_key (const char *filename, contents = file_to_g_byte_array (filename, error); if (contents) { - format = crypto_verify_private_key_data (contents->data, contents->len, password, error); + format = crypto_verify_private_key_data (contents->data, contents->len, password, out_is_encrypted, error); g_byte_array_free (contents, TRUE); } return format; diff --git a/libnm-core/crypto.h b/libnm-core/crypto.h index 9173ba2203..b7b7dc4ae7 100644 --- a/libnm-core/crypto.h +++ b/libnm-core/crypto.h @@ -48,16 +48,16 @@ gboolean crypto_init (GError **error); void crypto_deinit (void); -GByteArray *crypto_decrypt_private_key_data (const guint8 *data, - gsize data_len, - const char *password, - NMCryptoKeyType *out_key_type, - GError **error); +GByteArray *crypto_decrypt_openssl_private_key_data (const guint8 *data, + gsize data_len, + const char *password, + NMCryptoKeyType *out_key_type, + GError **error); -GByteArray *crypto_decrypt_private_key (const char *file, - const char *password, - NMCryptoKeyType *out_key_type, - GError **error); +GByteArray *crypto_decrypt_openssl_private_key (const char *file, + const char *password, + NMCryptoKeyType *out_key_type, + GError **error); GByteArray *crypto_load_and_verify_certificate (const char *file, NMCryptoFileFormat *out_file_format, @@ -70,10 +70,12 @@ gboolean crypto_is_pkcs12_data (const guint8 *data, gsize len); NMCryptoFileFormat crypto_verify_private_key_data (const guint8 *data, gsize data_len, const char *password, + gboolean *out_is_encrypted, GError **error); NMCryptoFileFormat crypto_verify_private_key (const char *file, const char *password, + gboolean *out_is_encrypted, GError **error); /* Internal utils API bits for crypto providers */ diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c index 7f07eccc55..d5e17b97a4 100644 --- a/libnm-core/nm-setting-8021x.c +++ b/libnm-core/nm-setting-8021x.c @@ -1752,7 +1752,7 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *setting, * given, that it decrypts the private key. */ if (key_path) { - format = crypto_verify_private_key (key_path, password, &local_err); + format = crypto_verify_private_key (key_path, password, NULL, &local_err); if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) { g_set_error_literal (error, NM_CONNECTION_ERROR, @@ -2062,7 +2062,7 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting, * given, that it decrypts the private key. */ if (key_path) { - format = crypto_verify_private_key (key_path, password, &local_err); + format = crypto_verify_private_key (key_path, password, NULL, &local_err); if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) { g_set_error_literal (error, NM_CONNECTION_ERROR, @@ -2206,11 +2206,11 @@ need_private_key_password (GBytes *blob, /* Private key password is required */ if (password) { if (path) - format = crypto_verify_private_key (path, password, NULL); + format = crypto_verify_private_key (path, password, NULL, NULL); else if (blob) format = crypto_verify_private_key_data (g_bytes_get_data (blob, NULL), g_bytes_get_size (blob), - password, NULL); + password, NULL, NULL); else g_warning ("%s: unknown private key password scheme", __func__); } diff --git a/libnm-core/tests/Makefile.am b/libnm-core/tests/Makefile.am index dc8c40080b..a21c131cb5 100644 --- a/libnm-core/tests/Makefile.am +++ b/libnm-core/tests/Makefile.am @@ -48,6 +48,7 @@ EXTRA_DIST = \ certs/ca-no-ending-newline.pem \ certs/test-key-only.pem \ certs/test-key-only-decrypted.der \ + certs/test-key-only-decrypted.pem \ certs/pkcs8-enc-key.pem \ certs/pkcs8-noenc-key.pem \ certs/pkcs8-decrypted.der \ diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c index b7a2b87bf8..c159cc2057 100644 --- a/libnm-core/tests/test-crypto.c +++ b/libnm-core/tests/test-crypto.c @@ -137,7 +137,7 @@ test_load_private_key (const char *path, GByteArray *array, *decrypted; GError *error = NULL; - array = crypto_decrypt_private_key (path, password, &key_type, &error); + array = crypto_decrypt_openssl_private_key (path, password, &key_type, &error); /* Even if the password is wrong, we should determine the key type */ g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); @@ -175,9 +175,10 @@ test_load_pkcs12 (const char *path, int expected_error) { NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + gboolean is_encrypted = FALSE; GError *error = NULL; - format = crypto_verify_private_key (path, password, &error); + format = crypto_verify_private_key (path, password, &is_encrypted, &error); if (expected_error != -1) { g_assert_error (error, NM_CRYPTO_ERROR, expected_error); g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN); @@ -185,6 +186,7 @@ test_load_pkcs12 (const char *path, } else { g_assert_no_error (error); g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12); + g_assert (is_encrypted); } } @@ -192,12 +194,14 @@ static void test_load_pkcs12_no_password (const char *path) { NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + gboolean is_encrypted = FALSE; GError *error = NULL; /* We should still get a valid returned crypto file format */ - format = crypto_verify_private_key (path, NULL, &error); + format = crypto_verify_private_key (path, NULL, &is_encrypted, &error); g_assert_no_error (error); g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12); + g_assert (is_encrypted); } static void @@ -224,9 +228,10 @@ test_load_pkcs8 (const char *path, int expected_error) { NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + gboolean is_encrypted = FALSE; GError *error = NULL; - format = crypto_verify_private_key (path, password, &error); + format = crypto_verify_private_key (path, password, &is_encrypted, &error); if (expected_error != -1) { g_assert_error (error, NM_CRYPTO_ERROR, expected_error); g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN); @@ -234,6 +239,7 @@ test_load_pkcs8 (const char *path, } else { g_assert_no_error (error); g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_RAW_KEY); + g_assert (is_encrypted); } } @@ -267,7 +273,7 @@ test_encrypt_private_key (const char *path, GByteArray *array, *encrypted, *re_decrypted; GError *error = NULL; - array = crypto_decrypt_private_key (path, password, &key_type, &error); + array = crypto_decrypt_openssl_private_key (path, password, &key_type, &error); g_assert_no_error (error); g_assert (array != NULL); g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); @@ -282,8 +288,8 @@ test_encrypt_private_key (const char *path, /* Then re-decrypt the private key */ key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; - re_decrypted = crypto_decrypt_private_key_data (encrypted->data, encrypted->len, - password, &key_type, &error); + re_decrypted = crypto_decrypt_openssl_private_key_data (encrypted->data, encrypted->len, + password, &key_type, &error); g_assert_no_error (error); g_assert (re_decrypted != NULL); g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); From 1c4f41c61013d79a32eeac246d204c2f378e6915 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 30 Oct 2014 11:15:44 -0400 Subject: [PATCH 4/4] libnm-core: add nm_utils_file_is_certificate() and _file_is_private_key() Add nm-utils methods to check if a file is a certificate or private key file. nm-applet currently has its own internal versions of these, but they ended up having to duplicate a bunch of logic that we already have in crypto.c. --- libnm-core/nm-utils.c | 76 ++++++++++++++++++- libnm-core/nm-utils.h | 2 + .../tests/certs/test-key-only-decrypted.pem | 27 +++++++ libnm-core/tests/test-crypto.c | 30 ++++++++ libnm/libnm.ver | 2 + 5 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 libnm-core/tests/certs/test-key-only-decrypted.pem diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index a6bf2f9e3e..d91de32141 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -2236,17 +2236,91 @@ nm_utils_rsa_key_encrypt_aes (const guint8 *data, error); } +static gboolean +file_has_extension (const char *filename, const char *extensions[]) +{ + const char *ext; + int 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; + GByteArray *cert; + + g_return_val_if_fail (filename != NULL, FALSE); + + if (!file_has_extension (filename, extensions)) + return FALSE; + + cert = crypto_load_and_verify_certificate (filename, &file_format, NULL); + if (cert) + g_byte_array_unref (cert); + + 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); + g_return_val_if_fail (out_encrypted == NULL || *out_encrypted == FALSE, FALSE); + + if (!file_has_extension (filename, extensions)) + return FALSE; + + return 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 * - * Utility function to find out if the @filename is in PKCS#12 format. + * 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 crypto_is_pkcs12_file (filename, NULL); } diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h index a4253927be..dcfae00e09 100644 --- a/libnm-core/nm-utils.h +++ b/libnm-core/nm-utils.h @@ -137,6 +137,8 @@ GByteArray *nm_utils_rsa_key_encrypt_aes (const guint8 *data, const char *in_password, char **out_password, GError **error); +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); guint32 nm_utils_wifi_freq_to_channel (guint32 freq); diff --git a/libnm-core/tests/certs/test-key-only-decrypted.pem b/libnm-core/tests/certs/test-key-only-decrypted.pem new file mode 100644 index 0000000000..1a25da5e7d --- /dev/null +++ b/libnm-core/tests/certs/test-key-only-decrypted.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAztLp+/SkzmaHzIst0sO4+r7qUwiVnidKBHgxoTbS5UL1dvck +cbjTEP23V4ZoKQIb6ZMrr8B+PVgWNBAlhX4oLUL8NH/WTwrntrlAUcjliWDNc1Fj +Z+FZNjFe0IdLXZeKQiLTQvKDYnmERVvYIJfi0TQjXuy/ikF8rYBQ85scUV3kKRzB +xnyhAHAP9nl3AyL1S6t2yiCr4U5TbIZo6dYPbpVLtbXP02zUc9vAPR0gIHKrPiW7 +P81fLXf91wuo6wxzwD90JxdWzzGaqe3BOSfHqul3SPRtVok1XHlb9i+Mn5O8ExzQ +dF8wGxVDcY7/Gt9lZWnCilqrBEqA3iApjUgcgwIDAQABAoIBAQC77HCmepf04ryp +Yhz00NoXG7mWUMqBtXlPrlaKAWKG5dxbiBwZKLK/UYlxgbLK8BuklBCx1Nnfq1Yh +YDp3nTWsSp0WpsF3eJUqNhD3Pu8xcD+9dEo6bUu+LgXUu9oC5Fq/1RzYS7qNk5RX +4Sf0FY4GQLWS3tL7MJ20mE71yg5k7qRbDydOyhTh1m1CpRYONWxSsWVLM8KGRDJp +iF0cdPfD5yoPFpgDk8gwzrnXJH2Wqzv8GvyYykRK5AW7tE50y0rTAM42WZ7YS6aZ +FNMmtYxeyzXLY3LgPP0uko5anz3OXRcqCfHfFANG0y7B9MehbrjMgI6S1BbzFl07 +V1zVQVqhAoGBAPIfrWMlh1fHlRh4iRGXK2Hvxyv2oNz9KvQ4qRaLV9ejRDzdt7Pi +/utbi5LGBuDw9016nXM3I77b6PukHzsHFnWGRnyRSbkMMt6mE17nggmNqcpFWfE8 +E7HcKMhk4gbuo5AHD3Ee1Gac2AUDnzYiE+sS6WI3O9d77cc5ych5jZ+nAoGBANqt +VZCttjY0E+hEyTP37eaE8u0jfdK8AflTJlNUHWKXglES525iu8I/Bso8KaQYsYF3 +SezGRd3KQepQhtMjFKfSpF+tbnboP57Y3XGo8xhbxqV4kRX+XGsVoW3Vg2nPKBrR ++dIY5nMwua+gkHWp9RDcemD2reiIZBVx95fK8dfFAoGAdCSH2pBs/MlrFqLzNTHr +iH4pb0hN39O9YAsx6POMfo79s6izbyHLIID4Ub6WHB7ashrIHjVr+yin+NXAeWMr +/dIcS7Kxx4c3e5/0mMi6kvSWZsWfoF0uIVo3YfEqjyK36OXKHXwpbNN9t+IF5ESy +g0e+FfPiy7nR1Ig+5+CO8+8CgYEAp/75+Ug677FaidouaMpT7gC9UAkwJLFjItQK +YYIBgTi8WOSY/2jCrhwVb1CA/RwrYjbuiARasGUt9oEe0x3kRHnC5e4rKxaJqdMZ +bLRK7a+0EHNrouXiwjG/7s1VQ/ht6wzdS9btVBlezdogoQSMzQNU0SExwa7mlMMV +X3v+B7ECgYAK+Yt4jnLH1LNWoDTU0Ug5hyXsQXV8lVBSnrkvS7GtP6ZA/4OqG7lJ +/bTYFZGoiAGzOnC+YlAqSIu45CEnpr2xBsThQiWUVxspmQD1lEWWFcd77DPUwn3C +59pLgx0AqJE3n6lBOwehiXbFKBdVzX8PfPZpuCK6qc/RiTILktwURA== +-----END RSA PRIVATE KEY----- diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c index c159cc2057..b9e958d7b8 100644 --- a/libnm-core/tests/test-crypto.c +++ b/libnm-core/tests/test-crypto.c @@ -109,6 +109,8 @@ test_cert (gconstpointer test_data) g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_X509); g_byte_array_free (array, TRUE); + + g_assert (nm_utils_file_is_certificate (path)); } static GByteArray * @@ -134,9 +136,13 @@ test_load_private_key (const char *path, int expected_error) { NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + gboolean is_encrypted = FALSE; GByteArray *array, *decrypted; GError *error = NULL; + g_assert (nm_utils_file_is_private_key (path, &is_encrypted)); + g_assert (is_encrypted); + array = crypto_decrypt_openssl_private_key (path, password, &key_type, &error); /* Even if the password is wrong, we should determine the key type */ g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); @@ -178,6 +184,8 @@ test_load_pkcs12 (const char *path, gboolean is_encrypted = FALSE; GError *error = NULL; + g_assert (nm_utils_file_is_private_key (path, NULL)); + format = crypto_verify_private_key (path, password, &is_encrypted, &error); if (expected_error != -1) { g_assert_error (error, NM_CRYPTO_ERROR, expected_error); @@ -197,6 +205,8 @@ 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)); + /* We should still get a valid returned crypto file format */ format = crypto_verify_private_key (path, NULL, &is_encrypted, &error); g_assert_no_error (error); @@ -231,6 +241,8 @@ test_load_pkcs8 (const char *path, gboolean is_encrypted = FALSE; GError *error = NULL; + g_assert (nm_utils_file_is_private_key (path, NULL)); + format = crypto_verify_private_key (path, password, &is_encrypted, &error); if (expected_error != -1) { g_assert_error (error, NM_CRYPTO_ERROR, expected_error); @@ -329,6 +341,21 @@ test_key (gconstpointer test_data) g_strfreev (parts); } +static void +test_key_decrypted (gconstpointer test_data) +{ + const char *file = (const char *) test_data; + gboolean is_encrypted = FALSE; + char *path; + + path = g_build_filename (TEST_CERT_DIR, file, NULL); + + g_assert (nm_utils_file_is_private_key (path, &is_encrypted)); + g_assert (!is_encrypted); + + g_free (path); +} + static void test_pkcs12 (gconstpointer test_data) { @@ -418,6 +445,9 @@ main (int argc, char **argv) g_test_add_data_func ("/libnm/crypto/key/aes", "test-aes-key.pem, test-aes-password", test_key); + g_test_add_data_func ("/libnm/crypto/key/decrypted", + "test-key-only-decrypted.pem", + test_key_decrypted); g_test_add_data_func ("/libnm/crypto/PKCS#12/1", "test-cert.p12, test", diff --git a/libnm/libnm.ver b/libnm/libnm.ver index ae28e58e3e..f8baca50f8 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -756,7 +756,9 @@ global: nm_utils_check_virtual_device_compatibility; nm_utils_deinit; nm_utils_escape_ssid; + nm_utils_file_is_certificate; nm_utils_file_is_pkcs12; + nm_utils_file_is_private_key; nm_utils_hexstr2bin; nm_utils_hwaddr_atoba; nm_utils_hwaddr_aton;