libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
2008-05-19 07:43:13 +00:00
|
|
|
/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
|
|
|
|
*
|
|
|
|
* Dan Williams <dcbw@redhat.com>
|
|
|
|
*
|
2008-07-27 20:03:46 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
2008-05-19 07:43:13 +00:00
|
|
|
*
|
2008-07-27 20:03:46 +00:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
2008-05-19 07:43:13 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2008-07-27 20:03:46 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
2008-05-19 07:43:13 +00:00
|
|
|
*
|
2008-07-27 20:03:46 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301 USA.
|
2008-05-19 07:43:13 +00:00
|
|
|
*
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
* (C) Copyright 2007 - 2009 Red Hat, Inc.
|
2008-05-19 07:43:13 +00:00
|
|
|
*/
|
|
|
|
|
2011-03-14 06:00:56 +00:00
|
|
|
#include "config.h"
|
2008-05-19 07:43:13 +00:00
|
|
|
#include <glib.h>
|
|
|
|
#include <glib/gi18n.h>
|
|
|
|
|
|
|
|
#include <gcrypt.h>
|
|
|
|
#include <gnutls/gnutls.h>
|
|
|
|
#include <gnutls/x509.h>
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
#include <gnutls/pkcs12.h>
|
2008-05-19 07:43:13 +00:00
|
|
|
|
|
|
|
#include "crypto.h"
|
|
|
|
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
#define SALT_LEN 8
|
|
|
|
|
2008-09-08 18:35:21 +00:00
|
|
|
static gboolean initialized = FALSE;
|
2008-08-26 03:29:18 +00:00
|
|
|
|
2008-05-19 07:43:13 +00:00
|
|
|
gboolean
|
|
|
|
crypto_init (GError **error)
|
|
|
|
{
|
2008-09-08 18:35:21 +00:00
|
|
|
if (initialized)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (gnutls_global_init() != 0) {
|
|
|
|
gnutls_global_deinit();
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_INIT_FAILED,
|
|
|
|
"%s",
|
|
|
|
_("Failed to initialize the crypto engine."));
|
|
|
|
return FALSE;
|
2008-09-05 18:10:39 +00:00
|
|
|
}
|
2008-09-08 18:35:21 +00:00
|
|
|
|
|
|
|
initialized = TRUE;
|
2008-05-19 07:43:13 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
crypto_deinit (void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
crypto_md5_hash (const char *salt,
|
|
|
|
const gsize salt_len,
|
|
|
|
const char *password,
|
|
|
|
gsize password_len,
|
|
|
|
char *buffer,
|
|
|
|
gsize buflen,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
gcry_md_hd_t ctx;
|
|
|
|
gcry_error_t err;
|
|
|
|
int nkey = buflen;
|
|
|
|
const gsize digest_len = 16;
|
|
|
|
int count = 0;
|
|
|
|
char digest[MD5_HASH_LEN];
|
|
|
|
char *p = buffer;
|
|
|
|
|
2008-08-26 03:29:18 +00:00
|
|
|
if (salt)
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
g_return_val_if_fail (salt_len >= SALT_LEN, FALSE);
|
2008-08-26 03:29:18 +00:00
|
|
|
|
2008-05-19 07:43:13 +00:00
|
|
|
g_return_val_if_fail (password != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (password_len > 0, FALSE);
|
|
|
|
g_return_val_if_fail (buffer != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (buflen > 0, FALSE);
|
|
|
|
|
|
|
|
err = gcry_md_open (&ctx, GCRY_MD_MD5, 0);
|
|
|
|
if (err) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_MD5_INIT_FAILED,
|
|
|
|
_("Failed to initialize the MD5 engine: %s / %s."),
|
|
|
|
gcry_strsource (err), gcry_strerror (err));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (nkey > 0) {
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
if (count++)
|
|
|
|
gcry_md_write (ctx, digest, digest_len);
|
|
|
|
gcry_md_write (ctx, password, password_len);
|
2008-08-26 03:29:18 +00:00
|
|
|
if (salt)
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
gcry_md_write (ctx, salt, SALT_LEN); /* Only use 8 bytes of salt */
|
2008-05-19 07:43:13 +00:00
|
|
|
gcry_md_final (ctx);
|
|
|
|
memcpy (digest, gcry_md_read (ctx, 0), digest_len);
|
|
|
|
gcry_md_reset (ctx);
|
|
|
|
|
|
|
|
while (nkey && (i < digest_len)) {
|
|
|
|
*(p++) = digest[i++];
|
|
|
|
nkey--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
memset (digest, 0, sizeof (digest));
|
|
|
|
gcry_md_close (ctx);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
crypto_decrypt (const char *cipher,
|
|
|
|
int key_type,
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
GByteArray *data,
|
2008-05-19 07:43:13 +00:00
|
|
|
const char *iv,
|
|
|
|
const gsize iv_len,
|
|
|
|
const char *key,
|
|
|
|
const gsize key_len,
|
|
|
|
gsize *out_len,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
gcry_cipher_hd_t ctx;
|
|
|
|
gcry_error_t err;
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
int cipher_mech, i;
|
2008-05-19 07:43:13 +00:00
|
|
|
char *output = NULL;
|
|
|
|
gboolean success = FALSE;
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
gsize pad_len, real_iv_len;
|
2008-05-19 07:43:13 +00:00
|
|
|
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
|
2008-05-19 07:43:13 +00:00
|
|
|
cipher_mech = GCRY_CIPHER_3DES;
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
real_iv_len = SALT_LEN;
|
|
|
|
} else if (!strcmp (cipher, CIPHER_DES_CBC)) {
|
2008-05-19 07:43:13 +00:00
|
|
|
cipher_mech = GCRY_CIPHER_DES;
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
real_iv_len = SALT_LEN;
|
|
|
|
} else {
|
2008-05-19 07:43:13 +00:00
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_UNKNOWN_CIPHER,
|
|
|
|
_("Private key cipher '%s' was unknown."),
|
|
|
|
cipher);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
if (iv_len < real_iv_len) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_RAW_IV_INVALID,
|
|
|
|
_("Invalid IV length (must be at least %zd)."),
|
|
|
|
real_iv_len);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
output = g_malloc0 (data->len);
|
2008-05-19 07:43:13 +00:00
|
|
|
|
|
|
|
err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
|
|
|
|
if (err) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CIPHER_INIT_FAILED,
|
|
|
|
_("Failed to initialize the decryption cipher context: %s / %s."),
|
|
|
|
gcry_strsource (err), gcry_strerror (err));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = gcry_cipher_setkey (ctx, key, key_len);
|
|
|
|
if (err) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CIPHER_SET_KEY_FAILED,
|
|
|
|
_("Failed to set symmetric key for decryption: %s / %s."),
|
|
|
|
gcry_strsource (err), gcry_strerror (err));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = gcry_cipher_setiv (ctx, iv, iv_len);
|
|
|
|
if (err) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CIPHER_SET_IV_FAILED,
|
|
|
|
_("Failed to set IV for decryption: %s / %s."),
|
|
|
|
gcry_strsource (err), gcry_strerror (err));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
err = gcry_cipher_decrypt (ctx, output, data->len, data->data, data->len);
|
2008-05-19 07:43:13 +00:00
|
|
|
if (err) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED,
|
|
|
|
_("Failed to decrypt the private key: %s / %s."),
|
|
|
|
gcry_strsource (err), gcry_strerror (err));
|
|
|
|
goto out;
|
|
|
|
}
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
pad_len = output[data->len - 1];
|
|
|
|
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
/* Check if the padding at the end of the decrypted data is valid */
|
|
|
|
if (pad_len == 0 || pad_len > real_iv_len) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED,
|
|
|
|
_("Failed to decrypt the private key: unexpected padding length."));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
/* Validate tail padding; last byte is the padding size, and all pad bytes
|
|
|
|
* should contain the padding size.
|
|
|
|
*/
|
|
|
|
for (i = 1; i <= pad_len; ++i) {
|
|
|
|
if (output[data->len - i] != pad_len) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED,
|
|
|
|
_("Failed to decrypt the private key."));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
2008-05-19 07:43:13 +00:00
|
|
|
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
*out_len = data->len - pad_len;
|
2008-05-19 07:43:13 +00:00
|
|
|
success = TRUE;
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (!success) {
|
|
|
|
if (output) {
|
|
|
|
/* Don't expose key material */
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
memset (output, 0, data->len);
|
2008-05-19 07:43:13 +00:00
|
|
|
g_free (output);
|
|
|
|
output = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gcry_cipher_close (ctx);
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
char *
|
|
|
|
crypto_encrypt (const char *cipher,
|
|
|
|
const GByteArray *data,
|
|
|
|
const char *iv,
|
|
|
|
const gsize iv_len,
|
|
|
|
const char *key,
|
|
|
|
gsize key_len,
|
|
|
|
gsize *out_len,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
gcry_cipher_hd_t ctx;
|
|
|
|
gcry_error_t err;
|
|
|
|
int cipher_mech;
|
|
|
|
char *output = NULL;
|
|
|
|
gboolean success = FALSE;
|
|
|
|
gsize padded_buf_len, pad_len, output_len;
|
|
|
|
char *padded_buf = NULL;
|
|
|
|
guint32 i;
|
|
|
|
|
|
|
|
if (!strcmp (cipher, CIPHER_DES_EDE3_CBC))
|
|
|
|
cipher_mech = GCRY_CIPHER_3DES;
|
|
|
|
else {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_UNKNOWN_CIPHER,
|
|
|
|
_("Private key cipher '%s' was unknown."),
|
|
|
|
cipher);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If data->len % ivlen == 0, then we add another complete block
|
|
|
|
* onto the end so that the decrypter knows there's padding.
|
|
|
|
*/
|
|
|
|
pad_len = iv_len - (data->len % iv_len);
|
|
|
|
output_len = padded_buf_len = data->len + pad_len;
|
|
|
|
padded_buf = g_malloc0 (padded_buf_len);
|
|
|
|
|
|
|
|
memcpy (padded_buf, data->data, data->len);
|
|
|
|
for (i = 0; i < pad_len; i++)
|
|
|
|
padded_buf[data->len + i] = (guint8) (pad_len & 0xFF);
|
|
|
|
|
|
|
|
output = g_malloc0 (output_len);
|
|
|
|
|
|
|
|
err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
|
|
|
|
if (err) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CIPHER_INIT_FAILED,
|
|
|
|
_("Failed to initialize the encryption cipher context: %s / %s."),
|
|
|
|
gcry_strsource (err), gcry_strerror (err));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = gcry_cipher_setkey (ctx, key, key_len);
|
|
|
|
if (err) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CIPHER_SET_KEY_FAILED,
|
|
|
|
_("Failed to set symmetric key for encryption: %s / %s."),
|
|
|
|
gcry_strsource (err), gcry_strerror (err));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* gcrypt only wants 8 bytes of the IV (same as the DES block length) */
|
|
|
|
err = gcry_cipher_setiv (ctx, iv, SALT_LEN);
|
|
|
|
if (err) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CIPHER_SET_IV_FAILED,
|
|
|
|
_("Failed to set IV for encryption: %s / %s."),
|
|
|
|
gcry_strsource (err), gcry_strerror (err));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = gcry_cipher_encrypt (ctx, output, output_len, padded_buf, padded_buf_len);
|
|
|
|
if (err) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED,
|
|
|
|
_("Failed to encrypt the data: %s / %s."),
|
|
|
|
gcry_strsource (err), gcry_strerror (err));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_len = output_len;
|
|
|
|
success = TRUE;
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (padded_buf) {
|
|
|
|
memset (padded_buf, 0, padded_buf_len);
|
|
|
|
g_free (padded_buf);
|
|
|
|
padded_buf = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
if (output) {
|
|
|
|
/* Don't expose key material */
|
|
|
|
memset (output, 0, output_len);
|
|
|
|
g_free (output);
|
|
|
|
output = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gcry_cipher_close (ctx);
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
NMCryptoFileFormat
|
2008-05-19 07:43:13 +00:00
|
|
|
crypto_verify_cert (const unsigned char *data,
|
|
|
|
gsize len,
|
|
|
|
GError **error)
|
|
|
|
{
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
gnutls_x509_crt_t der;
|
2008-05-19 07:43:13 +00:00
|
|
|
gnutls_datum dt;
|
|
|
|
int err;
|
|
|
|
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
err = gnutls_x509_crt_init (&der);
|
2008-05-19 07:43:13 +00:00
|
|
|
if (err < 0) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CERT_FORMAT_INVALID,
|
|
|
|
_("Error initializing certificate data: %s"),
|
|
|
|
gnutls_strerror (err));
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
|
2008-05-19 07:43:13 +00:00
|
|
|
}
|
|
|
|
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
/* Try DER first */
|
2008-05-19 07:43:13 +00:00
|
|
|
dt.data = (unsigned char *) data;
|
|
|
|
dt.size = len;
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
err = gnutls_x509_crt_import (der, &dt, GNUTLS_X509_FMT_DER);
|
|
|
|
if (err == GNUTLS_E_SUCCESS) {
|
|
|
|
gnutls_x509_crt_deinit (der);
|
|
|
|
return NM_CRYPTO_FILE_FORMAT_X509;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* And PEM next */
|
|
|
|
err = gnutls_x509_crt_import (der, &dt, GNUTLS_X509_FMT_PEM);
|
|
|
|
gnutls_x509_crt_deinit (der);
|
|
|
|
if (err == GNUTLS_E_SUCCESS)
|
|
|
|
return NM_CRYPTO_FILE_FORMAT_X509;
|
|
|
|
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CERT_FORMAT_INVALID,
|
|
|
|
_("Couldn't decode certificate: %s"),
|
|
|
|
gnutls_strerror (err));
|
|
|
|
return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
crypto_verify_pkcs12 (const GByteArray *data,
|
|
|
|
const char *password,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
gnutls_pkcs12_t p12;
|
|
|
|
gnutls_datum dt;
|
|
|
|
gboolean success = FALSE;
|
|
|
|
int err;
|
2008-05-19 07:43:13 +00:00
|
|
|
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
g_return_val_if_fail (data != NULL, FALSE);
|
|
|
|
|
|
|
|
dt.data = (unsigned char *) data->data;
|
|
|
|
dt.size = data->len;
|
|
|
|
|
|
|
|
err = gnutls_pkcs12_init (&p12);
|
2008-05-19 07:43:13 +00:00
|
|
|
if (err < 0) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
NM_CRYPTO_ERR_DECODE_FAILED,
|
|
|
|
_("Couldn't initialize PKCS#12 decoder: %s"),
|
2008-05-19 07:43:13 +00:00
|
|
|
gnutls_strerror (err));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-11-13 Dan Williams <dcbw@redhat.com>
Add support for PKCS#12 private keys (bgo #558982)
* libnm-util/crypto.c
libnm-util/crypto.h
- (parse_old_openssl_key_file): rename from parse_key_file(); adapt to
take a GByteArray instead of a filename
- (file_to_g_byte_array): handle private key files too
- (decrypt_key): take a GByteArray rather than data + len
- (crypto_get_private_key_data): refactor crypto_get_private_key() into
one function that takes a filename, and one that takes raw data;
detect pkcs#12 files as well
- (crypto_load_and_verify_certificate): detect file type
- (crypto_is_pkcs12_data, crypto_is_pkcs12_file): add pkcs#12 detection
functions
* libnm-util/crypto_gnutls.c
- (crypto_decrypt): take GByteArray rather than data + len; fix a bug
whereby tail padding was incorrectly handled, leading to erroneous
successes when trying to decrypt the data
- (crypto_verify_cert): rework somewhat
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/crypto_nss.c
- (crypto_init): enable various pkcs#12 ciphers
- (crypto_decrypt): take a GByteArray rather than data + len
- (crypto_verify_cert): clean up
- (crypto_verify_pkcs12): validate pkcs#12 keys
* libnm-util/test-crypto.c
- Handle pkcs#12 keys
* libnm-util/nm-setting-8021x.c
libnm-util/nm-setting-8021x.h
libnm-util/libnm-util.ver
- Add two new properties, 'private-key-password' and
'phase2-private-key-password', to be used in conjunction with
pkcs#12 keys
- (nm_setting_802_1x_set_ca_cert_from_file,
nm_setting_802_1x_set_client_cert_from_file,
nm_setting_802_1x_set_phase2_ca_cert_from_file,
nm_setting_802_1x_set_phase2_client_from_file): return certificate
type
- (nm_setting_802_1x_get_private_key_password,
nm_setting_802_1x_get_phase2_private_key_password): return private
key passwords
- (nm_setting_802_1x_set_private_key_from_file,
nm_setting_802_1x_set_phase2_private_key_from_file): set the private
key from a file, and update the private key password at the same time
- (nm_setting_802_1x_get_private_key_type,
nm_setting_802_1x_get_phase2_private_key_type): return the private
key type
* src/supplicant-manager/nm-supplicant-settings-verify.c
- Whitelist private key passwords
* src/supplicant-manager/nm-supplicant-config.c
- (nm_supplicant_config_add_setting_8021x): for pkcs#12 private keys,
add the private key password to the supplicant config, but do not
add the client certificate (as required by wpa_supplicant)
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4280 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-13 21:19:08 +00:00
|
|
|
/* DER first */
|
|
|
|
err = gnutls_pkcs12_import (p12, &dt, GNUTLS_X509_FMT_DER, 0);
|
|
|
|
if (err < 0) {
|
|
|
|
/* PEM next */
|
|
|
|
err = gnutls_pkcs12_import (p12, &dt, GNUTLS_X509_FMT_PEM, 0);
|
|
|
|
if (err < 0) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_FILE_FORMAT_INVALID,
|
|
|
|
_("Couldn't decode PKCS#12 file: %s"),
|
|
|
|
gnutls_strerror (err));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = gnutls_pkcs12_verify_mac (p12, password);
|
|
|
|
if (err == GNUTLS_E_SUCCESS)
|
|
|
|
success = TRUE;
|
|
|
|
else {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED,
|
|
|
|
_("Couldn't verify PKCS#12 file: %s"),
|
|
|
|
gnutls_strerror (err));
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
gnutls_pkcs12_deinit (p12);
|
|
|
|
return success;
|
2008-05-19 07:43:13 +00:00
|
|
|
}
|
|
|
|
|
2011-05-12 15:09:18 +00:00
|
|
|
gboolean
|
|
|
|
crypto_verify_pkcs8 (const GByteArray *data,
|
|
|
|
gboolean is_encrypted,
|
|
|
|
const char *password,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
gnutls_x509_privkey_t p8;
|
|
|
|
gnutls_datum dt;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
g_return_val_if_fail (data != NULL, FALSE);
|
|
|
|
|
|
|
|
dt.data = (unsigned char *) data->data;
|
|
|
|
dt.size = data->len;
|
|
|
|
|
|
|
|
err = gnutls_x509_privkey_init (&p8);
|
|
|
|
if (err < 0) {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_DECODE_FAILED,
|
|
|
|
_("Couldn't initialize PKCS#8 decoder: %s"),
|
|
|
|
gnutls_strerror (err));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = gnutls_x509_privkey_import_pkcs8 (p8,
|
|
|
|
&dt,
|
|
|
|
GNUTLS_X509_FMT_DER,
|
|
|
|
is_encrypted ? password : NULL,
|
|
|
|
is_encrypted ? 0 : GNUTLS_PKCS_PLAIN);
|
|
|
|
gnutls_x509_privkey_deinit (p8);
|
|
|
|
|
|
|
|
if (err < 0) {
|
|
|
|
if (err == GNUTLS_E_UNKNOWN_CIPHER_TYPE) {
|
|
|
|
/* HACK: gnutls doesn't support all the cipher types that openssl
|
|
|
|
* can use with PKCS#8, so if we encounter one, we have to assume
|
|
|
|
* the given password works. gnutls needs to unsuckify, apparently.
|
|
|
|
* Specifically, by default openssl uses pbeWithMD5AndDES-CBC
|
|
|
|
* which gnutls does not support.
|
|
|
|
*/
|
|
|
|
} else {
|
|
|
|
g_set_error (error, NM_CRYPTO_ERROR,
|
|
|
|
NM_CRYPTO_ERR_FILE_FORMAT_INVALID,
|
|
|
|
_("Couldn't decode PKCS#8 file: %s"),
|
|
|
|
gnutls_strerror (err));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
libnm-util: add nm_utils_rsa_key_encrypt() and fix crypto padding mixups
To be backwards compatible clients need to handle both paths to private
keys and the decrypted private key data, which is what used to get passed
in the private-key and phase2-private-key attributes of the 802.1x setting.
When moving a connection around between system-settings and user-settings,
if the private key is decrypted data, the settings service needs to store
that decrypted data somewhere so that the key can be sent to NM during
the connection process.
But we don't want to store the decrypted private key data, so we have to
re-encrypt it (possibly generating a private key password if one wasn't
sent with the decrypted data) and save it to disk, then send NM a path
to that private key during connection.
To help clients do this, and so that they don't have to carry around
multiple crypto implementations depending on whether they want to use
NSS or gnutls/gcrypt, add a helper to libnm-util.
Furthermore, I misunderstood a bunch of stuff with crypto padding when
writing the encrypt/decrypt functions long ago, so fix that up. Don't
return padding as part of the decrypted data, and make sure to verify
the padding's expected lengths and values when decrypting. Many thanks
to Nalin Dahyabhai for pointing me in the right direction.
2009-09-15 23:01:50 +00:00
|
|
|
gboolean
|
|
|
|
crypto_randomize (void *buffer, gsize buffer_len, GError **error)
|
|
|
|
{
|
|
|
|
gcry_randomize (buffer, buffer_len, GCRY_STRONG_RANDOM);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|