build: move nm-crypto to separate directory "src/libnm-crypto"
libnm-core currently has a dependency on crypto libraries (either "gnutls", "nss" or "null"). We need this huge dependency for few cases. Move the crypto code to a separate static library"src/libnm-crypto/libnm-crypto.la". The reasoning is that it becomes clearer where we have this dependency, to use it more consciously, and to be better see how it's used. We clearly need the crypto functionality in libnm. But do we also need it in the daemon? Could we ever link the daemon without crypto libraries? The goal of splitting the crypto part out, to better understand the crypto dependency.
This commit is contained in:
@@ -2,45 +2,6 @@
|
||||
|
||||
libnm_core_impl_inc = include_directories('.')
|
||||
|
||||
if crypto_nss_dep.found()
|
||||
libnm_crypto_nss = static_library(
|
||||
'nm-crypto-nss',
|
||||
sources: 'nm-crypto-nss.c',
|
||||
dependencies: [
|
||||
libnm_core_public_dep,
|
||||
crypto_nss_dep,
|
||||
],
|
||||
)
|
||||
endif
|
||||
|
||||
if crypto_gnutls_dep.found()
|
||||
libnm_crypto_gnutls = static_library(
|
||||
'nm-crypto-gnutls',
|
||||
sources: 'nm-crypto-gnutls.c',
|
||||
dependencies: [
|
||||
libnm_core_public_dep,
|
||||
crypto_gnutls_dep,
|
||||
],
|
||||
)
|
||||
endif
|
||||
|
||||
libnm_crypto_null = static_library(
|
||||
'nm-crypto-null',
|
||||
sources: 'nm-crypto-null.c',
|
||||
dependencies: [
|
||||
libnm_core_public_dep,
|
||||
],
|
||||
)
|
||||
|
||||
if crypto == 'nss'
|
||||
libnm_crypto = libnm_crypto_nss
|
||||
elif crypto == 'gnutls'
|
||||
libnm_crypto = libnm_crypto_gnutls
|
||||
else
|
||||
assert(crypto == 'null', 'Unexpected setting "crypto=' + crypto + '"')
|
||||
libnm_crypto = libnm_crypto_null
|
||||
endif
|
||||
|
||||
libnm_core_settings_sources = files(
|
||||
'nm-setting-6lowpan.c',
|
||||
'nm-setting-8021x.c',
|
||||
@@ -99,7 +60,6 @@ libnm_core_settings_sources = files(
|
||||
|
||||
libnm_core_impl_sources = files(
|
||||
'nm-connection.c',
|
||||
'nm-crypto.c',
|
||||
'nm-dbus-utils.c',
|
||||
'nm-errors.c',
|
||||
'nm-keyfile-utils.c',
|
||||
|
@@ -1,414 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Dan Williams <dcbw@redhat.com>
|
||||
* Copyright (C) 2007 - 2015 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
|
||||
|
||||
#include "nm-crypto-impl.h"
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include <gnutls/x509.h>
|
||||
#include <gnutls/pkcs12.h>
|
||||
|
||||
#include "libnm-glib-aux/nm-secret-utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_get_cipher_info(NMCryptoCipherType cipher, int *out_cipher_mech, guint8 *out_real_iv_len)
|
||||
{
|
||||
static const int cipher_mechs[] = {
|
||||
[NM_CRYPTO_CIPHER_DES_EDE3_CBC] = GNUTLS_CIPHER_3DES_CBC,
|
||||
[NM_CRYPTO_CIPHER_DES_CBC] = GNUTLS_CIPHER_DES_CBC,
|
||||
[NM_CRYPTO_CIPHER_AES_128_CBC] = GNUTLS_CIPHER_AES_128_CBC,
|
||||
[NM_CRYPTO_CIPHER_AES_192_CBC] = GNUTLS_CIPHER_AES_192_CBC,
|
||||
[NM_CRYPTO_CIPHER_AES_256_CBC] = GNUTLS_CIPHER_AES_256_CBC,
|
||||
};
|
||||
|
||||
g_return_val_if_fail(_NM_INT_NOT_NEGATIVE(cipher)
|
||||
&& (gsize) cipher < G_N_ELEMENTS(cipher_mechs),
|
||||
FALSE);
|
||||
|
||||
if (cipher_mechs[cipher] == 0)
|
||||
return FALSE;
|
||||
|
||||
NM_SET_OUT(out_cipher_mech, cipher_mechs[cipher]);
|
||||
NM_SET_OUT(out_real_iv_len, nm_crypto_cipher_get_info(cipher)->real_iv_len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
_nm_crypto_init(GError **error)
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
|
||||
if (initialized)
|
||||
return TRUE;
|
||||
|
||||
if (gnutls_global_init() != 0) {
|
||||
gnutls_global_deinit();
|
||||
g_set_error_literal(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Failed to initialize the crypto engine."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
initialized = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
guint8 *
|
||||
_nmtst_crypto_decrypt(NMCryptoCipherType cipher,
|
||||
const guint8 *data,
|
||||
gsize data_len,
|
||||
const guint8 *iv,
|
||||
gsize iv_len,
|
||||
const guint8 *key,
|
||||
gsize key_len,
|
||||
gsize *out_len,
|
||||
GError **error)
|
||||
{
|
||||
gnutls_cipher_hd_t ctx;
|
||||
gnutls_datum_t key_dt, iv_dt;
|
||||
int err;
|
||||
int cipher_mech;
|
||||
nm_auto_clear_secret_ptr NMSecretPtr output = {0};
|
||||
guint8 pad_i, pad_len;
|
||||
guint8 real_iv_len;
|
||||
|
||||
if (!_get_cipher_info(cipher, &cipher_mech, &real_iv_len)) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
|
||||
_("Unsupported key cipher for decryption"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_nm_crypto_init(error))
|
||||
return NULL;
|
||||
|
||||
if (iv_len < real_iv_len) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_INVALID_DATA,
|
||||
_("Invalid IV length (must be at least %u)."),
|
||||
(guint) real_iv_len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
output.len = data_len;
|
||||
output.bin = g_malloc(data_len);
|
||||
|
||||
key_dt.data = (unsigned char *) key;
|
||||
key_dt.size = key_len;
|
||||
iv_dt.data = (unsigned char *) iv;
|
||||
iv_dt.size = iv_len;
|
||||
|
||||
err = gnutls_cipher_init(&ctx, cipher_mech, &key_dt, &iv_dt);
|
||||
if (err < 0) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to initialize the decryption cipher context: %s (%s)"),
|
||||
gnutls_strerror_name(err),
|
||||
gnutls_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = gnutls_cipher_decrypt2(ctx, data, data_len, output.bin, output.len);
|
||||
|
||||
gnutls_cipher_deinit(ctx);
|
||||
|
||||
if (err < 0) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to decrypt the private key: %s (%s)"),
|
||||
gnutls_strerror_name(err),
|
||||
gnutls_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pad_len = output.len > 0 ? output.bin[output.len - 1] : 0;
|
||||
|
||||
/* Check if the padding at the end of the decrypted data is valid */
|
||||
if (pad_len == 0 || pad_len > real_iv_len) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to decrypt the private key: unexpected padding length."));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Validate tail padding; last byte is the padding size, and all pad bytes
|
||||
* should contain the padding size.
|
||||
*/
|
||||
for (pad_i = 1; pad_i <= pad_len; ++pad_i) {
|
||||
if (output.bin[data_len - pad_i] != pad_len) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to decrypt the private key."));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*out_len = output.len - pad_len;
|
||||
return g_steal_pointer(&output.bin);
|
||||
}
|
||||
|
||||
guint8 *
|
||||
_nmtst_crypto_encrypt(NMCryptoCipherType cipher,
|
||||
const guint8 *data,
|
||||
gsize data_len,
|
||||
const guint8 *iv,
|
||||
gsize iv_len,
|
||||
const guint8 *key,
|
||||
gsize key_len,
|
||||
gsize *out_len,
|
||||
GError **error)
|
||||
{
|
||||
gnutls_cipher_hd_t ctx;
|
||||
gnutls_datum_t key_dt, iv_dt;
|
||||
int err;
|
||||
int cipher_mech;
|
||||
nm_auto_clear_secret_ptr NMSecretPtr output = {0};
|
||||
nm_auto_clear_secret_ptr NMSecretPtr padded_buf = {0};
|
||||
gsize i, pad_len;
|
||||
|
||||
nm_assert(iv_len);
|
||||
|
||||
if (cipher == NM_CRYPTO_CIPHER_DES_CBC || !_get_cipher_info(cipher, &cipher_mech, NULL)) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
|
||||
_("Unsupported key cipher for encryption"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_nm_crypto_init(error))
|
||||
return NULL;
|
||||
|
||||
key_dt.data = (unsigned char *) key;
|
||||
key_dt.size = key_len;
|
||||
iv_dt.data = (unsigned char *) iv;
|
||||
iv_dt.size = iv_len;
|
||||
|
||||
err = gnutls_cipher_init(&ctx, cipher_mech, &key_dt, &iv_dt);
|
||||
if (err < 0) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
|
||||
_("Failed to initialize the encryption cipher context: %s (%s)"),
|
||||
gnutls_strerror_name(err),
|
||||
gnutls_strerror(err));
|
||||
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);
|
||||
|
||||
padded_buf.len = data_len + pad_len;
|
||||
padded_buf.bin = g_malloc(padded_buf.len);
|
||||
memcpy(padded_buf.bin, data, data_len);
|
||||
for (i = 0; i < pad_len; i++)
|
||||
padded_buf.bin[data_len + i] = (guint8) (pad_len & 0xFF);
|
||||
|
||||
output.len = padded_buf.len;
|
||||
output.bin = g_malloc(output.len);
|
||||
|
||||
err = gnutls_cipher_encrypt2(ctx, padded_buf.bin, padded_buf.len, output.bin, output.len);
|
||||
|
||||
gnutls_cipher_deinit(ctx);
|
||||
|
||||
if (err < 0) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
|
||||
_("Failed to encrypt the data: %s (%s)"),
|
||||
gnutls_strerror_name(err),
|
||||
gnutls_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*out_len = output.len;
|
||||
return g_steal_pointer(&output.bin);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error)
|
||||
{
|
||||
gnutls_x509_crt_t der;
|
||||
gnutls_datum_t dt;
|
||||
int err;
|
||||
|
||||
if (!_nm_crypto_init(error))
|
||||
return FALSE;
|
||||
|
||||
err = gnutls_x509_crt_init(&der);
|
||||
if (err < 0) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_INVALID_DATA,
|
||||
_("Error initializing certificate data: %s"),
|
||||
gnutls_strerror(err));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Try DER first */
|
||||
dt.data = (unsigned char *) data;
|
||||
dt.size = len;
|
||||
err = gnutls_x509_crt_import(der, &dt, GNUTLS_X509_FMT_DER);
|
||||
if (err == GNUTLS_E_SUCCESS) {
|
||||
gnutls_x509_crt_deinit(der);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* 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 TRUE;
|
||||
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_INVALID_DATA,
|
||||
_("Couldn't decode certificate: %s"),
|
||||
gnutls_strerror(err));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *password, GError **error)
|
||||
{
|
||||
gnutls_pkcs12_t p12;
|
||||
gnutls_datum_t dt;
|
||||
int err;
|
||||
|
||||
g_return_val_if_fail(data != NULL, FALSE);
|
||||
|
||||
if (!_nm_crypto_init(error))
|
||||
return FALSE;
|
||||
|
||||
dt.data = (unsigned char *) data;
|
||||
dt.size = data_len;
|
||||
|
||||
err = gnutls_pkcs12_init(&p12);
|
||||
if (err < 0) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Couldn't initialize PKCS#12 decoder: %s"),
|
||||
gnutls_strerror(err));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* 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_ERROR_INVALID_DATA,
|
||||
_("Couldn't decode PKCS#12 file: %s"),
|
||||
gnutls_strerror(err));
|
||||
gnutls_pkcs12_deinit(p12);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
err = gnutls_pkcs12_verify_mac(p12, password);
|
||||
|
||||
gnutls_pkcs12_deinit(p12);
|
||||
|
||||
if (err != GNUTLS_E_SUCCESS) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Couldn't verify PKCS#12 file: %s"),
|
||||
gnutls_strerror(err));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_verify_pkcs8(const guint8 *data,
|
||||
gsize data_len,
|
||||
gboolean is_encrypted,
|
||||
const char *password,
|
||||
GError **error)
|
||||
{
|
||||
gnutls_x509_privkey_t p8;
|
||||
gnutls_datum_t dt;
|
||||
int err;
|
||||
|
||||
g_return_val_if_fail(data != NULL, FALSE);
|
||||
|
||||
if (!_nm_crypto_init(error))
|
||||
return FALSE;
|
||||
|
||||
err = gnutls_x509_privkey_init(&p8);
|
||||
if (err < 0) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Couldn't initialize PKCS#8 decoder: %s"),
|
||||
gnutls_strerror(err));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dt.data = (unsigned char *) data;
|
||||
dt.size = data_len;
|
||||
|
||||
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 < 3.5.4 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_ERROR_INVALID_DATA,
|
||||
_("Couldn't decode PKCS#8 file: %s"),
|
||||
gnutls_strerror(err));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error)
|
||||
{
|
||||
if (!_nm_crypto_init(error))
|
||||
return FALSE;
|
||||
|
||||
gnutls_rnd(GNUTLS_RND_RANDOM, buffer, buffer_len);
|
||||
return TRUE;
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Dan Williams <dcbw@redhat.com>
|
||||
* Copyright (C) 2007 - 2018 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NM_CRYPTO_IMPL_H__
|
||||
#define __NM_CRYPTO_IMPL_H__
|
||||
|
||||
#include "nm-crypto.h"
|
||||
#include "libnm-base/nm-base.h"
|
||||
|
||||
gboolean _nm_crypto_init(GError **error);
|
||||
|
||||
gboolean _nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error);
|
||||
|
||||
gboolean _nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error);
|
||||
|
||||
gboolean
|
||||
_nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *password, GError **error);
|
||||
|
||||
gboolean _nm_crypto_verify_pkcs8(const guint8 *data,
|
||||
gsize data_len,
|
||||
gboolean is_encrypted,
|
||||
const char *password,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
guint8 *_nmtst_crypto_encrypt(NMCryptoCipherType cipher,
|
||||
const guint8 *data,
|
||||
gsize data_len,
|
||||
const guint8 *iv,
|
||||
gsize iv_len,
|
||||
const guint8 *key,
|
||||
gsize key_len,
|
||||
gsize *out_len,
|
||||
GError **error);
|
||||
|
||||
guint8 *_nmtst_crypto_decrypt(NMCryptoCipherType cipher,
|
||||
const guint8 *data,
|
||||
gsize data_len,
|
||||
const guint8 *iv,
|
||||
gsize iv_len,
|
||||
const guint8 *key,
|
||||
gsize key_len,
|
||||
gsize *out_len,
|
||||
GError **error);
|
||||
|
||||
#endif /* __NM_CRYPTO_IMPL_H__ */
|
@@ -1,551 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Dan Williams <dcbw@redhat.com>
|
||||
* Copyright (C) 2007 - 2009 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
|
||||
|
||||
#include "nm-crypto-impl.h"
|
||||
|
||||
NM_PRAGMA_WARNING_DISABLE("-Wstrict-prototypes")
|
||||
#include <prinit.h>
|
||||
#include <nss.h>
|
||||
#include <pk11pub.h>
|
||||
#include <pkcs11t.h>
|
||||
#include <cert.h>
|
||||
#include <prerror.h>
|
||||
#include <p12.h>
|
||||
#include <ciferfam.h>
|
||||
#include <p12plcy.h>
|
||||
NM_PRAGMA_WARNING_REENABLE
|
||||
|
||||
#include "libnm-glib-aux/nm-secret-utils.h"
|
||||
#include "libnm-base/nm-base.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_get_cipher_info(NMCryptoCipherType cipher,
|
||||
CK_MECHANISM_TYPE *out_cipher_mech,
|
||||
guint8 *out_real_iv_len)
|
||||
{
|
||||
static const CK_MECHANISM_TYPE cipher_mechs[] = {
|
||||
[NM_CRYPTO_CIPHER_DES_EDE3_CBC] = CKM_DES3_CBC_PAD,
|
||||
[NM_CRYPTO_CIPHER_DES_CBC] = CKM_DES_CBC_PAD,
|
||||
[NM_CRYPTO_CIPHER_AES_128_CBC] = CKM_AES_CBC_PAD,
|
||||
[NM_CRYPTO_CIPHER_AES_192_CBC] = CKM_AES_CBC_PAD,
|
||||
[NM_CRYPTO_CIPHER_AES_256_CBC] = CKM_AES_CBC_PAD,
|
||||
};
|
||||
|
||||
g_return_val_if_fail(_NM_INT_NOT_NEGATIVE(cipher)
|
||||
&& (gsize) cipher < G_N_ELEMENTS(cipher_mechs),
|
||||
FALSE);
|
||||
|
||||
if (!cipher_mechs[cipher])
|
||||
return FALSE;
|
||||
|
||||
NM_SET_OUT(out_cipher_mech, cipher_mechs[cipher]);
|
||||
NM_SET_OUT(out_real_iv_len, nm_crypto_cipher_get_info(cipher)->real_iv_len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
_nm_crypto_init(GError **error)
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
SECStatus ret;
|
||||
|
||||
if (initialized)
|
||||
return TRUE;
|
||||
|
||||
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1);
|
||||
ret = NSS_NoDB_Init(NULL);
|
||||
if (ret != SECSuccess) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Failed to initialize the crypto engine: %d."),
|
||||
PR_GetError());
|
||||
PR_Cleanup();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
|
||||
SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
|
||||
SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
|
||||
SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
|
||||
SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
|
||||
SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
|
||||
SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
|
||||
|
||||
initialized = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
guint8 *
|
||||
_nmtst_crypto_decrypt(NMCryptoCipherType cipher,
|
||||
const guint8 *data,
|
||||
gsize data_len,
|
||||
const guint8 *iv,
|
||||
gsize iv_len,
|
||||
const guint8 *key,
|
||||
gsize key_len,
|
||||
gsize *out_len,
|
||||
GError **error)
|
||||
{
|
||||
CK_MECHANISM_TYPE cipher_mech;
|
||||
PK11SlotInfo *slot = NULL;
|
||||
SECItem key_item;
|
||||
PK11SymKey *sym_key = NULL;
|
||||
SECItem *sec_param = NULL;
|
||||
PK11Context *ctx = NULL;
|
||||
nm_auto_clear_secret_ptr NMSecretPtr output = {0};
|
||||
SECStatus s;
|
||||
gboolean success = FALSE;
|
||||
int decrypted_len = 0;
|
||||
unsigned extra = 0;
|
||||
unsigned pad_len = 0;
|
||||
guint32 i;
|
||||
guint8 real_iv_len;
|
||||
|
||||
if (!_get_cipher_info(cipher, &cipher_mech, &real_iv_len)) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
|
||||
_("Unsupported key cipher for decryption"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (iv_len < real_iv_len) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_INVALID_DATA,
|
||||
_("Invalid IV length (must be at least %u)."),
|
||||
(guint) real_iv_len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_nm_crypto_init(error))
|
||||
return NULL;
|
||||
|
||||
slot = PK11_GetBestSlot(cipher_mech, NULL);
|
||||
if (!slot) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Failed to initialize the decryption cipher slot."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
key_item.data = (unsigned char *) key;
|
||||
key_item.len = key_len;
|
||||
sym_key = PK11_ImportSymKey(slot, cipher_mech, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, NULL);
|
||||
if (!sym_key) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to set symmetric key for decryption."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
key_item.data = (unsigned char *) iv;
|
||||
key_item.len = real_iv_len;
|
||||
sec_param = PK11_ParamFromIV(cipher_mech, &key_item);
|
||||
if (!sec_param) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to set IV for decryption."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx = PK11_CreateContextBySymKey(cipher_mech, CKA_DECRYPT, sym_key, sec_param);
|
||||
if (!ctx) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to initialize the decryption context."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
output.len = data_len;
|
||||
output.bin = g_malloc(data_len);
|
||||
|
||||
s = PK11_CipherOp(ctx,
|
||||
(unsigned char *) output.bin,
|
||||
&decrypted_len,
|
||||
output.len,
|
||||
data,
|
||||
data_len);
|
||||
if (s != SECSuccess) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to decrypt the private key: %d."),
|
||||
PORT_GetError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (decrypted_len > data_len) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to decrypt the private key: decrypted data too large."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
s = PK11_DigestFinal(ctx,
|
||||
(unsigned char *) &output.bin[decrypted_len],
|
||||
&extra,
|
||||
data_len - decrypted_len);
|
||||
if (s != SECSuccess) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to finalize decryption of the private key: %d."),
|
||||
PORT_GetError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
decrypted_len += extra;
|
||||
pad_len = data_len - decrypted_len;
|
||||
|
||||
/* Check if the padding at the end of the decrypted data is valid */
|
||||
if (pad_len == 0 || pad_len > real_iv_len) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to decrypt the private key: unexpected padding length."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Validate tail padding; last byte is the padding size, and all pad bytes
|
||||
* should contain the padding size.
|
||||
*/
|
||||
for (i = pad_len; i > 0; i--) {
|
||||
if (output.bin[data_len - i] != pad_len) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Failed to decrypt the private key."));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
out:
|
||||
if (ctx)
|
||||
PK11_DestroyContext(ctx, PR_TRUE);
|
||||
if (sym_key)
|
||||
PK11_FreeSymKey(sym_key);
|
||||
if (sec_param)
|
||||
SECITEM_FreeItem(sec_param, PR_TRUE);
|
||||
if (slot)
|
||||
PK11_FreeSlot(slot);
|
||||
|
||||
if (!success)
|
||||
return NULL;
|
||||
|
||||
if (decrypted_len < output.len)
|
||||
nm_explicit_bzero(&output.bin[decrypted_len], output.len - decrypted_len);
|
||||
*out_len = decrypted_len;
|
||||
return g_steal_pointer(&output.bin);
|
||||
}
|
||||
|
||||
guint8 *
|
||||
_nmtst_crypto_encrypt(NMCryptoCipherType cipher,
|
||||
const guint8 *data,
|
||||
gsize data_len,
|
||||
const guint8 *iv,
|
||||
gsize iv_len,
|
||||
const guint8 *key,
|
||||
gsize key_len,
|
||||
gsize *out_len,
|
||||
GError **error)
|
||||
{
|
||||
SECStatus ret;
|
||||
CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD;
|
||||
PK11SlotInfo *slot = NULL;
|
||||
SECItem key_item = {.data = (unsigned char *) key, .len = key_len};
|
||||
SECItem iv_item = {.data = (unsigned char *) iv, .len = iv_len};
|
||||
PK11SymKey *sym_key = NULL;
|
||||
SECItem *sec_param = NULL;
|
||||
PK11Context *ctx = NULL;
|
||||
nm_auto_clear_secret_ptr NMSecretPtr padded_buf = {0};
|
||||
nm_auto_clear_secret_ptr NMSecretPtr output = {0};
|
||||
int encrypted_len = 0, i;
|
||||
gboolean success = FALSE;
|
||||
gsize pad_len;
|
||||
|
||||
if (cipher == NM_CRYPTO_CIPHER_DES_CBC || !_get_cipher_info(cipher, &cipher_mech, NULL)) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
|
||||
_("Unsupported key cipher for encryption"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_nm_crypto_init(error))
|
||||
return NULL;
|
||||
|
||||
slot = PK11_GetBestSlot(cipher_mech, NULL);
|
||||
if (!slot) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Failed to initialize the encryption cipher slot."));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sym_key = PK11_ImportSymKey(slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL);
|
||||
if (!sym_key) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
|
||||
_("Failed to set symmetric key for encryption."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
sec_param = PK11_ParamFromIV(cipher_mech, &iv_item);
|
||||
if (!sec_param) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
|
||||
_("Failed to set IV for encryption."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx = PK11_CreateContextBySymKey(cipher_mech, CKA_ENCRYPT, sym_key, sec_param);
|
||||
if (!ctx) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
|
||||
_("Failed to initialize the encryption context."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
padded_buf.len = data_len + pad_len;
|
||||
padded_buf.bin = g_malloc(padded_buf.len);
|
||||
|
||||
memcpy(padded_buf.bin, data, data_len);
|
||||
for (i = 0; i < pad_len; i++)
|
||||
padded_buf.bin[data_len + i] = (guint8) (pad_len & 0xFF);
|
||||
|
||||
output.len = padded_buf.len;
|
||||
output.bin = g_malloc(output.len);
|
||||
|
||||
ret =
|
||||
PK11_CipherOp(ctx, output.bin, &encrypted_len, output.len, padded_buf.bin, padded_buf.len);
|
||||
if (ret != SECSuccess) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
|
||||
_("Failed to encrypt: %d."),
|
||||
PORT_GetError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (encrypted_len != output.len) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
|
||||
_("Unexpected amount of data after encrypting."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
out:
|
||||
if (ctx)
|
||||
PK11_DestroyContext(ctx, PR_TRUE);
|
||||
if (sec_param)
|
||||
SECITEM_FreeItem(sec_param, PR_TRUE);
|
||||
if (sym_key)
|
||||
PK11_FreeSymKey(sym_key);
|
||||
if (slot)
|
||||
PK11_FreeSlot(slot);
|
||||
|
||||
if (!success)
|
||||
return NULL;
|
||||
|
||||
*out_len = output.len;
|
||||
return g_steal_pointer(&output.bin);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error)
|
||||
{
|
||||
CERTCertificate *cert;
|
||||
|
||||
if (!_nm_crypto_init(error))
|
||||
return FALSE;
|
||||
|
||||
/* Try DER/PEM first */
|
||||
cert = CERT_DecodeCertFromPackage((char *) data, len);
|
||||
if (!cert) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_INVALID_DATA,
|
||||
_("Couldn't decode certificate: %d"),
|
||||
PORT_GetError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CERT_DestroyCertificate(cert);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *password, GError **error)
|
||||
{
|
||||
SEC_PKCS12DecoderContext *p12ctx = NULL;
|
||||
SECItem pw = {0};
|
||||
PK11SlotInfo *slot = NULL;
|
||||
SECStatus s;
|
||||
gboolean success = FALSE;
|
||||
|
||||
g_return_val_if_fail(!error || !*error, FALSE);
|
||||
|
||||
if (!_nm_crypto_init(error))
|
||||
return FALSE;
|
||||
|
||||
/* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do
|
||||
* any conversions for us.
|
||||
*/
|
||||
if (password && *password) {
|
||||
nm_auto_clear_secret_ptr NMSecretPtr ucs2_password = {0};
|
||||
|
||||
if (g_utf8_validate(password, -1, NULL)) {
|
||||
long ucs2_chars;
|
||||
|
||||
ucs2_password.bin =
|
||||
(guint8 *) g_utf8_to_utf16(password, strlen(password), NULL, &ucs2_chars, NULL);
|
||||
|
||||
/* cannot fail, because password is valid UTF-8*/
|
||||
nm_assert(ucs2_password.bin && ucs2_chars > 0);
|
||||
|
||||
ucs2_password.len = ucs2_chars * 2;
|
||||
}
|
||||
|
||||
if (!ucs2_password.bin || ucs2_password.len == 0) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_INVALID_PASSWORD,
|
||||
_("Password must be UTF-8"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pw.data = PORT_ZAlloc(ucs2_password.len + 2);
|
||||
memcpy(pw.data, ucs2_password.bin, ucs2_password.len);
|
||||
pw.len = ucs2_password.len + 2;
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
{
|
||||
guint16 *p, *p_end;
|
||||
|
||||
p_end = (guint16 *) &(((guint8 *) pw.data)[ucs2_password.len]);
|
||||
for (p = (guint16 *) pw.data; p < p_end; p++)
|
||||
*p = GUINT16_SWAP_LE_BE(*p);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
slot = PK11_GetInternalKeySlot();
|
||||
if (!slot) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Couldn't initialize slot"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
p12ctx = SEC_PKCS12DecoderStart(&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (!p12ctx) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Couldn't initialize PKCS#12 decoder: %d"),
|
||||
PORT_GetError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
s = SEC_PKCS12DecoderUpdate(p12ctx, (guint8 *) data, data_len);
|
||||
if (s != SECSuccess) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_INVALID_DATA,
|
||||
_("Couldn't decode PKCS#12 file: %d"),
|
||||
PORT_GetError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
s = SEC_PKCS12DecoderVerify(p12ctx);
|
||||
if (s != SECSuccess) {
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_DECRYPTION_FAILED,
|
||||
_("Couldn't verify PKCS#12 file: %d"),
|
||||
PORT_GetError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
out:
|
||||
if (p12ctx)
|
||||
SEC_PKCS12DecoderFinish(p12ctx);
|
||||
if (slot)
|
||||
PK11_FreeSlot(slot);
|
||||
|
||||
if (pw.data)
|
||||
SECITEM_ZfreeItem(&pw, PR_FALSE);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_verify_pkcs8(const guint8 *data,
|
||||
gsize data_len,
|
||||
gboolean is_encrypted,
|
||||
const char *password,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail(data != NULL, FALSE);
|
||||
|
||||
if (!_nm_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.
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error)
|
||||
{
|
||||
SECStatus s;
|
||||
|
||||
if (!_nm_crypto_init(error))
|
||||
return FALSE;
|
||||
|
||||
s = PK11_GenerateRandom(buffer, buffer_len);
|
||||
if (s != SECSuccess) {
|
||||
g_set_error_literal(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Could not generate random data."));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
@@ -1,103 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Christian Eggers <ceggers@arri.de>
|
||||
* Copyright (C) 2020 - 2022 ARRI Lighting
|
||||
*/
|
||||
|
||||
#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
|
||||
|
||||
#include "nm-crypto-impl.h"
|
||||
|
||||
#include "libnm-glib-aux/nm-secret-utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
_nm_crypto_init(GError **error)
|
||||
{
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Compiled without crypto support."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
guint8 *
|
||||
_nmtst_crypto_decrypt(NMCryptoCipherType cipher,
|
||||
const guint8 *data,
|
||||
gsize data_len,
|
||||
const guint8 *iv,
|
||||
gsize iv_len,
|
||||
const guint8 *key,
|
||||
gsize key_len,
|
||||
gsize *out_len,
|
||||
GError **error)
|
||||
{
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Compiled without crypto support."));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
guint8 *
|
||||
_nmtst_crypto_encrypt(NMCryptoCipherType cipher,
|
||||
const guint8 *data,
|
||||
gsize data_len,
|
||||
const guint8 *iv,
|
||||
gsize iv_len,
|
||||
const guint8 *key,
|
||||
gsize key_len,
|
||||
gsize *out_len,
|
||||
GError **error)
|
||||
{
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Compiled without crypto support."));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error)
|
||||
{
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Compiled without crypto support."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *password, GError **error)
|
||||
{
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Compiled without crypto support."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_verify_pkcs8(const guint8 *data,
|
||||
gsize data_len,
|
||||
gboolean is_encrypted,
|
||||
const char *password,
|
||||
GError **error)
|
||||
{
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Compiled without crypto support."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error)
|
||||
{
|
||||
g_set_error(error,
|
||||
_NM_CRYPTO_ERROR,
|
||||
_NM_CRYPTO_ERROR_FAILED,
|
||||
_("Compiled without crypto support."));
|
||||
return FALSE;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,96 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Dan Williams <dcbw@redhat.com>
|
||||
* Copyright (C) 2007 - 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NM_CRYPTO_H__
|
||||
#define __NM_CRYPTO_H__
|
||||
|
||||
typedef enum {
|
||||
NM_CRYPTO_CIPHER_UNKNOWN,
|
||||
NM_CRYPTO_CIPHER_DES_EDE3_CBC,
|
||||
NM_CRYPTO_CIPHER_DES_CBC,
|
||||
NM_CRYPTO_CIPHER_AES_128_CBC,
|
||||
NM_CRYPTO_CIPHER_AES_192_CBC,
|
||||
NM_CRYPTO_CIPHER_AES_256_CBC,
|
||||
} NMCryptoCipherType;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
NMCryptoCipherType cipher;
|
||||
guint8 digest_len;
|
||||
guint8 real_iv_len;
|
||||
} NMCryptoCipherInfo;
|
||||
|
||||
const NMCryptoCipherInfo *nm_crypto_cipher_get_info(NMCryptoCipherType cipher);
|
||||
const NMCryptoCipherInfo *nm_crypto_cipher_get_info_by_name(const char *cipher_name, gssize p_len);
|
||||
|
||||
typedef enum {
|
||||
NM_CRYPTO_KEY_TYPE_UNKNOWN = 0,
|
||||
NM_CRYPTO_KEY_TYPE_RSA,
|
||||
NM_CRYPTO_KEY_TYPE_DSA
|
||||
} NMCryptoKeyType;
|
||||
|
||||
typedef enum {
|
||||
NM_CRYPTO_FILE_FORMAT_UNKNOWN = 0,
|
||||
NM_CRYPTO_FILE_FORMAT_X509,
|
||||
NM_CRYPTO_FILE_FORMAT_RAW_KEY,
|
||||
NM_CRYPTO_FILE_FORMAT_PKCS12
|
||||
} NMCryptoFileFormat;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
GBytes *nm_crypto_read_file(const char *filename, GError **error);
|
||||
|
||||
gboolean nm_crypto_load_and_verify_certificate(const char *file,
|
||||
NMCryptoFileFormat *out_file_format,
|
||||
GBytes **out_certificat,
|
||||
GError **error);
|
||||
|
||||
gboolean nm_crypto_is_pkcs12_file(const char *file, GError **error);
|
||||
|
||||
gboolean nm_crypto_is_pkcs12_data(const guint8 *data, gsize len, GError **error);
|
||||
|
||||
NMCryptoFileFormat nm_crypto_verify_private_key_data(const guint8 *data,
|
||||
gsize data_len,
|
||||
const char *password,
|
||||
gboolean *out_is_encrypted,
|
||||
GError **error);
|
||||
|
||||
NMCryptoFileFormat nm_crypto_verify_private_key(const char *file,
|
||||
const char *password,
|
||||
gboolean *out_is_encrypted,
|
||||
GError **error);
|
||||
|
||||
gboolean nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
GBytes *nmtst_crypto_decrypt_openssl_private_key_data(const guint8 *data,
|
||||
gsize data_len,
|
||||
const char *password,
|
||||
NMCryptoKeyType *out_key_type,
|
||||
GError **error);
|
||||
|
||||
GBytes *nmtst_crypto_decrypt_openssl_private_key(const char *file,
|
||||
const char *password,
|
||||
NMCryptoKeyType *out_key_type,
|
||||
GError **error);
|
||||
|
||||
GBytes *nmtst_crypto_rsa_key_encrypt(const guint8 *data,
|
||||
gsize len,
|
||||
const char *in_password,
|
||||
char **out_password,
|
||||
GError **error);
|
||||
|
||||
guint8 *nmtst_crypto_make_des_aes_key(NMCryptoCipherType cipher,
|
||||
const guint8 *salt,
|
||||
gsize salt_len,
|
||||
const char *password,
|
||||
gsize *out_len,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NM_CRYPTO_H__ */
|
@@ -9,8 +9,8 @@
|
||||
#include "nm-setting-8021x.h"
|
||||
|
||||
#include "libnm-glib-aux/nm-secret-utils.h"
|
||||
#include "libnm-crypto/nm-crypto.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-crypto.h"
|
||||
#include "nm-utils-private.h"
|
||||
#include "nm-setting-private.h"
|
||||
#include "nm-core-enum-types.h"
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include <linux/pkt_sched.h>
|
||||
#include <linux/if_infiniband.h>
|
||||
|
||||
#include "libnm-crypto/nm-crypto.h"
|
||||
#include "libnm-glib-aux/nm-uuid.h"
|
||||
#include "libnm-glib-aux/nm-json-aux.h"
|
||||
#include "libnm-glib-aux/nm-str-buf.h"
|
||||
@@ -27,7 +28,6 @@
|
||||
#include "libnm-core-aux-intern/nm-common-macros.h"
|
||||
#include "nm-utils-private.h"
|
||||
#include "nm-setting-private.h"
|
||||
#include "nm-crypto.h"
|
||||
#include "nm-setting-bond.h"
|
||||
#include "nm-setting-bond-port.h"
|
||||
#include "nm-setting-bridge.h"
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nm-crypto-impl.h"
|
||||
#include "libnm-crypto/nm-crypto-impl.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-errors.h"
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
|
Reference in New Issue
Block a user