libnm-core: call crypto_init() on the fly

Rather than requiring crypto_init() to have been called beforehand,
just have every method that depends on it call it itself.

This required adding a GError argument to crypto_is_pkcs12_data(),
which in turn required a few other changes elsewhere.
This commit is contained in:
Dan Winship 2014-12-01 14:13:06 -05:00
parent 48ff21b5bc
commit bddc0de51e
7 changed files with 86 additions and 36 deletions

View file

@ -482,6 +482,9 @@ crypto_decrypt_openssl_private_key_data (const guint8 *data,
if (out_key_type)
g_return_val_if_fail (*out_key_type == NM_CRYPTO_KEY_TYPE_UNKNOWN, NULL);
if (!crypto_init (error))
return NULL;
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)
@ -527,6 +530,9 @@ crypto_decrypt_openssl_private_key (const char *file,
GByteArray *contents;
GByteArray *key = NULL;
if (!crypto_init (error))
return NULL;
contents = file_to_g_byte_array (file, error);
if (contents) {
key = crypto_decrypt_openssl_private_key_data (contents->data, contents->len,
@ -594,12 +600,15 @@ crypto_load_and_verify_certificate (const char *file,
g_return_val_if_fail (out_file_format != NULL, NULL);
g_return_val_if_fail (*out_file_format == NM_CRYPTO_FILE_FORMAT_UNKNOWN, NULL);
if (!crypto_init (error))
return NULL;
contents = file_to_g_byte_array (file, error);
if (!contents)
return NULL;
/* Check for PKCS#12 */
if (crypto_is_pkcs12_data (contents->data, contents->len)) {
if (crypto_is_pkcs12_data (contents->data, contents->len, NULL)) {
*out_file_format = NM_CRYPTO_FILE_FORMAT_PKCS12;
return contents;
}
@ -628,20 +637,26 @@ crypto_load_and_verify_certificate (const char *file,
gboolean
crypto_is_pkcs12_data (const guint8 *data,
gsize data_len)
gsize data_len,
GError **error)
{
GError *error = NULL;
GError *local = NULL;
gboolean success;
g_return_val_if_fail (data != NULL, FALSE);
success = crypto_verify_pkcs12 (data, data_len, NULL, &error);
if (!crypto_init (error))
return FALSE;
success = 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 (error) {
if (g_error_matches (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED))
if (local) {
if (g_error_matches (local, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED)) {
success = TRUE;
g_error_free (error);
g_error_free (local);
} else
g_propagate_error (error, local);
}
}
return success;
@ -655,9 +670,12 @@ crypto_is_pkcs12_file (const char *file, GError **error)
g_return_val_if_fail (file != NULL, FALSE);
if (!crypto_init (error))
return FALSE;
contents = file_to_g_byte_array (file, error);
if (contents) {
success = crypto_is_pkcs12_data (contents->data, contents->len);
success = crypto_is_pkcs12_data (contents->data, contents->len, error);
g_byte_array_free (contents, TRUE);
}
return success;
@ -681,8 +699,11 @@ crypto_verify_private_key_data (const guint8 *data,
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);
if (!crypto_init (error))
return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
/* Check for PKCS#12 first */
if (crypto_is_pkcs12_data (data, data_len)) {
if (crypto_is_pkcs12_data (data, data_len, NULL)) {
is_encrypted = TRUE;
if (!password || crypto_verify_pkcs12 (data, data_len, password, error))
format = NM_CRYPTO_FILE_FORMAT_PKCS12;
@ -727,7 +748,10 @@ crypto_verify_private_key (const char *filename,
GByteArray *contents;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (filename != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN);
if (!crypto_init (error))
return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
contents = file_to_g_byte_array (filename, error);
if (contents) {

View file

@ -63,7 +63,7 @@ GByteArray *crypto_load_and_verify_certificate (const char *file,
gboolean crypto_is_pkcs12_file (const char *file, GError **error);
gboolean crypto_is_pkcs12_data (const guint8 *data, gsize len);
gboolean crypto_is_pkcs12_data (const guint8 *data, gsize len, GError **error);
NMCryptoFileFormat crypto_verify_private_key_data (const guint8 *data,
gsize data_len,

View file

@ -75,6 +75,9 @@ crypto_decrypt (const char *cipher,
gboolean success = FALSE;
gsize pad_len, real_iv_len;
if (!crypto_init (error))
return NULL;
if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
cipher_mech = GCRY_CIPHER_3DES;
real_iv_len = SALT_LEN;
@ -196,6 +199,9 @@ crypto_encrypt (const char *cipher,
guint32 i;
gsize salt_len;
if (!crypto_init (error))
return NULL;
if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
cipher_mech = GCRY_CIPHER_3DES;
salt_len = SALT_LEN;
@ -291,6 +297,9 @@ crypto_verify_cert (const unsigned char *data,
gnutls_datum_t dt;
int err;
if (!crypto_init (error))
return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
err = gnutls_x509_crt_init (&der);
if (err < 0) {
g_set_error (error, NM_CRYPTO_ERROR,
@ -335,6 +344,9 @@ crypto_verify_pkcs12 (const guint8 *data,
g_return_val_if_fail (data != NULL, FALSE);
if (!crypto_init (error))
return FALSE;
dt.data = (unsigned char *) data;
dt.size = data_len;
@ -389,6 +401,9 @@ crypto_verify_pkcs8 (const guint8 *data,
g_return_val_if_fail (data != NULL, FALSE);
if (!crypto_init (error))
return FALSE;
dt.data = (unsigned char *) data;
dt.size = data_len;
@ -431,6 +446,9 @@ crypto_verify_pkcs8 (const guint8 *data,
gboolean
crypto_randomize (void *buffer, gsize buffer_len, GError **error)
{
if (!crypto_init (error))
return FALSE;
gcry_randomize (buffer, buffer_len, GCRY_STRONG_RANDOM);
return TRUE;
}

View file

@ -97,6 +97,9 @@ crypto_decrypt (const char *cipher,
unsigned int pad_len = 0, extra = 0;
guint32 i, real_iv_len = 0;
if (!crypto_init (error))
return NULL;
if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
cipher_mech = CKM_DES3_CBC_PAD;
real_iv_len = 8;
@ -264,6 +267,9 @@ crypto_encrypt (const char *cipher,
gboolean success = FALSE;
gsize padded_buf_len, pad_len;
if (!crypto_init (error))
return NULL;
if (!strcmp (cipher, CIPHER_DES_EDE3_CBC))
cipher_mech = CKM_DES3_CBC_PAD;
else if (!strcmp (cipher, CIPHER_AES_CBC))
@ -368,6 +374,9 @@ crypto_verify_cert (const unsigned char *data,
{
CERTCertificate *cert;
if (!crypto_init (error))
return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
/* Try DER/PEM first */
cert = CERT_DecodeCertFromPackage ((char *) data, len);
if (!cert) {
@ -401,6 +410,9 @@ crypto_verify_pkcs12 (const guint8 *data,
if (error)
g_return_val_if_fail (*error == NULL, FALSE);
if (!crypto_init (error))
return FALSE;
/* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do
* any conversions for us.
*/
@ -485,6 +497,9 @@ crypto_verify_pkcs8 (const guint8 *data,
{
g_return_val_if_fail (data != NULL, FALSE);
if (!crypto_init (error))
return FALSE;
/* NSS apparently doesn't do PKCS#8 natively, but you have to put the
* PKCS#8 key into a PKCS#12 file and import that?? So until we figure
* all that out, we can only assume the password is valid.
@ -497,6 +512,9 @@ crypto_randomize (void *buffer, gsize buffer_len, GError **error)
{
SECStatus s;
if (!crypto_init (error))
return FALSE;
s = PK11_GenerateRandom (buffer, buffer_len);
if (s != SECSuccess) {
g_set_error_literal (error, NM_CRYPTO_ERROR,

View file

@ -1871,15 +1871,15 @@ nm_setting_802_1x_get_private_key_format (NMSetting8021x *setting)
switch (nm_setting_802_1x_get_private_key_scheme (setting)) {
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
if (crypto_is_pkcs12_data (g_bytes_get_data (priv->private_key, NULL),
g_bytes_get_size (priv->private_key)))
g_bytes_get_size (priv->private_key),
NULL))
return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
case NM_SETTING_802_1X_CK_SCHEME_PATH:
path = nm_setting_802_1x_get_private_key_path (setting);
if (crypto_is_pkcs12_file (path, &error))
return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
if (error) {
/* Couldn't read the file or something */
if (error && error->domain == G_FILE_ERROR) {
g_error_free (error);
return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
}
@ -2151,15 +2151,15 @@ nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting)
switch (nm_setting_802_1x_get_phase2_private_key_scheme (setting)) {
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
if (crypto_is_pkcs12_data (g_bytes_get_data (priv->phase2_private_key, NULL),
g_bytes_get_size (priv->phase2_private_key)))
g_bytes_get_size (priv->phase2_private_key),
NULL))
return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
case NM_SETTING_802_1X_CK_SCHEME_PATH:
path = nm_setting_802_1x_get_phase2_private_key_path (setting);
if (crypto_is_pkcs12_file (path, &error))
return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
if (error) {
/* Couldn't read the file or something */
if (error && error->domain == G_FILE_ERROR) {
g_error_free (error);
return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
}
@ -2300,7 +2300,8 @@ verify_tls (NMSetting8021x *self, gboolean phase2, GError **error)
/* If the private key is PKCS#12, check that it matches the client cert */
if (crypto_is_pkcs12_data (g_bytes_get_data (priv->phase2_private_key, NULL),
g_bytes_get_size (priv->phase2_private_key))) {
g_bytes_get_size (priv->phase2_private_key),
NULL)) {
if (!g_bytes_equal (priv->phase2_private_key, priv->phase2_client_cert)) {
g_set_error (error,
NM_CONNECTION_ERROR,
@ -2347,7 +2348,8 @@ verify_tls (NMSetting8021x *self, gboolean phase2, GError **error)
/* If the private key is PKCS#12, check that it matches the client cert */
if (crypto_is_pkcs12_data (g_bytes_get_data (priv->private_key, NULL),
g_bytes_get_size (priv->private_key))) {
g_bytes_get_size (priv->private_key),
NULL)) {
if (!g_bytes_equal (priv->private_key, priv->client_cert)) {
g_set_error (error,
NM_CONNECTION_ERROR,
@ -3078,7 +3080,6 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
GError *error = NULL;
g_type_class_add_private (setting_class, sizeof (NMSetting8021xPrivate));
@ -3859,11 +3860,4 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
/* Initialize crypto lbrary. */
if (!nm_utils_init (&error)) {
g_warning ("Couldn't initilize nm-utils/crypto system: %d %s",
error->code, error->message);
g_error_free (error);
}
}

View file

@ -244,9 +244,6 @@ nm_utils_init (GError **error)
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
if (!crypto_init (error))
return FALSE;
_nm_dbus_errors_init ();
}
return TRUE;

View file

@ -221,15 +221,14 @@ test_is_pkcs12 (const char *path, gboolean expect_fail)
GError *error = NULL;
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)
if (expect_fail) {
g_assert_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA);
g_assert (!is_pkcs12);
else
} else {
g_assert_no_error (error);
g_assert (is_pkcs12);
}
}
static void