diff options
author | Dan Winship <danw@redhat.com> | 2014-11-21 08:55:22 -0500 |
---|---|---|
committer | Dan Winship <danw@redhat.com> | 2014-11-21 08:55:22 -0500 |
commit | b5ef91775db62e7cc1e262497b5cfee8971fb418 (patch) | |
tree | 2066f0d46a8bdae01684cdb3db3a03283e082a3f | |
parent | 4b7a736c4026451981b863cc4df2d4a2451a2f0c (diff) | |
parent | 1c4f41c61013d79a32eeac246d204c2f378e6915 (diff) | |
download | NetworkManager-b5ef91775db62e7cc1e262497b5cfee8971fb418.tar.gz |
libnm-core: merge branch 'cert-apis-bgo719768'
Misc updates to libnm-core certificate handling. (Prologue to nmtui
vpn editing work.)
https://bugzilla.gnome.org/show_bug.cgi?id=719768
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | libnm-core/crypto.c | 119 | ||||
-rw-r--r-- | libnm-core/crypto.h | 22 | ||||
-rw-r--r-- | libnm-core/nm-setting-8021x.c | 8 | ||||
-rw-r--r-- | libnm-core/nm-utils.c | 76 | ||||
-rw-r--r-- | libnm-core/nm-utils.h | 2 | ||||
-rw-r--r-- | libnm-core/tests/Makefile.am | 29 | ||||
-rw-r--r-- | libnm-core/tests/certs/ca-no-ending-newline.pem (renamed from libnm-util/tests/certs/ca-no-ending-newline.pem) | 0 | ||||
-rw-r--r-- | libnm-core/tests/certs/pkcs8-decrypted.der (renamed from libnm-util/tests/certs/pkcs8-decrypted.der) | bin | 1194 -> 1194 bytes | |||
-rw-r--r-- | libnm-core/tests/certs/pkcs8-enc-key.pem (renamed from libnm-util/tests/certs/pkcs8-enc-key.pem) | 0 | ||||
-rw-r--r-- | libnm-core/tests/certs/pkcs8-noenc-key.pem (renamed from libnm-util/tests/certs/pkcs8-noenc-key.pem) | 0 | ||||
-rw-r--r-- | libnm-core/tests/certs/test-aes-key.pem (renamed from libnm-util/tests/certs/test-aes-key.pem) | 0 | ||||
-rw-r--r-- | libnm-core/tests/certs/test-cert.p12 (renamed from libnm-util/tests/certs/test-cert.p12) | bin | 4092 -> 4092 bytes | |||
-rw-r--r-- | libnm-core/tests/certs/test-key-only-decrypted.der (renamed from libnm-util/tests/certs/test-key-only-decrypted.der) | bin | 1192 -> 1192 bytes | |||
-rw-r--r-- | libnm-core/tests/certs/test-key-only-decrypted.pem | 27 | ||||
-rw-r--r-- | libnm-core/tests/certs/test-key-only.pem (renamed from libnm-util/tests/certs/test-key-only.pem) | 0 | ||||
-rw-r--r-- | libnm-core/tests/certs/test2-cert.p12 (renamed from libnm-util/tests/certs/test2-cert.p12) | bin | 4136 -> 4136 bytes | |||
-rw-r--r-- | libnm-core/tests/certs/test2_ca_cert.pem (renamed from libnm-util/tests/certs/test2_ca_cert.pem) | 0 | ||||
-rw-r--r-- | libnm-core/tests/certs/test2_key_and_cert.pem (renamed from libnm-util/tests/certs/test2_key_and_cert.pem) | 0 | ||||
-rw-r--r-- | libnm-core/tests/certs/test_ca_cert.der (renamed from libnm-util/tests/certs/test_ca_cert.der) | bin | 1162 -> 1162 bytes | |||
-rw-r--r-- | libnm-core/tests/certs/test_ca_cert.pem (renamed from libnm-util/tests/certs/test_ca_cert.pem) | 0 | ||||
-rw-r--r-- | libnm-core/tests/certs/test_key_and_cert.pem (renamed from libnm-util/tests/certs/test_key_and_cert.pem) | 0 | ||||
-rw-r--r-- | libnm-core/tests/test-crypto.c | 245 | ||||
-rw-r--r-- | libnm-util/tests/Makefile.am | 4 | ||||
-rw-r--r-- | libnm-util/tests/certs/Makefile.am | 25 | ||||
-rw-r--r-- | libnm/libnm.ver | 2 |
26 files changed, 334 insertions, 226 deletions
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/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_private_key (const char *file, - 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_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/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/Makefile.am b/libnm-core/tests/Makefile.am index eea0fc198e..a21c131cb5 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,30 @@ 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/test-key-only-decrypted.pem \ + 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 index 664e299aa7..664e299aa7 100644 --- a/libnm-util/tests/certs/ca-no-ending-newline.pem +++ b/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 Binary files differindex 2cbdeb5e30..2cbdeb5e30 100644 --- a/libnm-util/tests/certs/pkcs8-decrypted.der +++ b/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 index 0d08f2d299..0d08f2d299 100644 --- a/libnm-util/tests/certs/pkcs8-enc-key.pem +++ b/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 index f73fb55ab2..f73fb55ab2 100644 --- a/libnm-util/tests/certs/pkcs8-noenc-key.pem +++ b/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 index aab8f463ca..aab8f463ca 100644 --- a/libnm-util/tests/certs/test-aes-key.pem +++ b/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 Binary files differindex ae4a683049..ae4a683049 100644 --- a/libnm-util/tests/certs/test-cert.p12 +++ b/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 Binary files differindex c8652537a6..c8652537a6 100644 --- a/libnm-util/tests/certs/test-key-only-decrypted.der +++ b/libnm-core/tests/certs/test-key-only-decrypted.der 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-util/tests/certs/test-key-only.pem b/libnm-core/tests/certs/test-key-only.pem index 5ef530e9ab..5ef530e9ab 100644 --- a/libnm-util/tests/certs/test-key-only.pem +++ b/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 Binary files differindex 9d5732b0a9..9d5732b0a9 100644 --- a/libnm-util/tests/certs/test2-cert.p12 +++ b/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 index 9a487ca4b4..9a487ca4b4 100644 --- a/libnm-util/tests/certs/test2_ca_cert.pem +++ b/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 index a668596eef..a668596eef 100644 --- a/libnm-util/tests/certs/test2_key_and_cert.pem +++ b/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 Binary files differindex e844f65b2c..e844f65b2c 100644 --- a/libnm-util/tests/certs/test_ca_cert.der +++ b/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 index faa3fc2905..faa3fc2905 100644 --- a/libnm-util/tests/certs/test_ca_cert.pem +++ b/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 index c00495d0b0..c00495d0b0 100644 --- a/libnm-util/tests/certs/test_key_and_cert.pem +++ b/libnm-core/tests/certs/test_key_and_cert.pem diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c index a61042e664..b9e958d7b8 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,15 +105,12 @@ 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); + + g_assert (nm_utils_file_is_certificate (path)); } static GByteArray * @@ -135,50 +133,41 @@ 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; + gboolean is_encrypted = FALSE; 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); - - 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); + 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); + + 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 +178,80 @@ 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; + gboolean is_encrypted = FALSE; 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); + 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); + 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); + g_assert (is_encrypted); } } 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; + 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, &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); + 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 -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; + gboolean is_encrypted = FALSE; 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); + 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); + 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); + g_assert (is_encrypted); } } @@ -285,51 +279,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); + 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); /* 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); + 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); /* 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 +323,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 (<key file>, <password>, [<decrypted key file>])"); + if (len != 2 && len != 3) + g_error ("wrong number of arguments (<key file>, <password>, [<decrypted key file>])"); 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); @@ -363,21 +342,36 @@ test_key (gconstpointer test_data) } 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) { char **parts, *path, *password; parts = g_strsplit ((const char *) test_data, ", ", -1); - ASSERT (g_strv_length (parts) == 2, "test-crypto", - "wrong number of arguments (<file>, <password>)"); + if (g_strv_length (parts) != 2) + g_error ("wrong number of arguments (<file>, <password>)"); 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 +383,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 (<file>, <password>)"); + if (g_strv_length (parts) != 2) + g_error ("wrong number of arguments (<file>, <password>)"); 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); @@ -451,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-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 - 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; |