diff options
17 files changed, 647 insertions, 336 deletions
diff --git a/plugins/pychrysalide/core/Makefile.am b/plugins/pychrysalide/core/Makefile.am index 6ba9fc8..5588c9f 100644 --- a/plugins/pychrysalide/core/Makefile.am +++ b/plugins/pychrysalide/core/Makefile.am @@ -15,8 +15,7 @@ libpychrysacore_la_SOURCES = \ constants.h constants.c \ logs.h logs.c \ module.h module.c \ - nox.h nox.c \ - secstorage.h secstorage.c + nox.h nox.c libpychrysacore_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT diff --git a/plugins/pychrysalide/core/module.c b/plugins/pychrysalide/core/module.c index 7eceddd..4af0403 100644 --- a/plugins/pychrysalide/core/module.c +++ b/plugins/pychrysalide/core/module.c @@ -35,7 +35,6 @@ //#include "params.h" //#include "processors.h" //#include "queue.h" -#include "secstorage.h" #include "../helpers.h" @@ -111,7 +110,6 @@ bool populate_core_module(void) //if (result) result = populate_core_module_with_params(); //if (result) result = populate_core_module_with_processors(); //if (result) result = populate_core_module_with_queue(); - if (result) result = populate_core_module_with_secstorage(); assert(result); diff --git a/plugins/pychrysalide/glibext/Makefile.am b/plugins/pychrysalide/glibext/Makefile.am index 2d45244..af1d9f2 100644 --- a/plugins/pychrysalide/glibext/Makefile.am +++ b/plugins/pychrysalide/glibext/Makefile.am @@ -26,6 +26,7 @@ libpychrysaglibext_la_SOURCES = \ module.h module.c \ objhole.h objhole.c \ portion.h portion.c \ + secstorage.h secstorage.c \ singleton.h singleton.c \ strbuilder.h strbuilder.c \ work.h work.c \ diff --git a/plugins/pychrysalide/glibext/module.c b/plugins/pychrysalide/glibext/module.c index 8adae07..6ce0709 100644 --- a/plugins/pychrysalide/glibext/module.c +++ b/plugins/pychrysalide/glibext/module.c @@ -43,6 +43,7 @@ #include "hashable.h" #include "objhole.h" #include "portion.h" +#include "secstorage.h" #include "singleton.h" #include "strbuilder.h" #include "work.h" @@ -121,6 +122,7 @@ bool populate_glibext_module(void) if (result) result = ensure_python_thick_object_is_registered(); if (result) result = ensure_python_binary_portion_is_registered(); if (result) result = ensure_python_generic_work_is_registered(); + if (result) result = ensure_python_secret_storage_is_registered(); if (result) result = ensure_python_singleton_factory_is_registered(); if (result) result = ensure_python_work_queue_is_registered(); diff --git a/plugins/pychrysalide/core/secstorage.c b/plugins/pychrysalide/glibext/secstorage.c index 67779af..b5adb7c 100644 --- a/plugins/pychrysalide/core/secstorage.c +++ b/plugins/pychrysalide/glibext/secstorage.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * secstorage.c - équivalent Python du fichier "core/secstorage.c" + * secstorage.c - équivalent Python du fichier "glibext/secstorage.c" * * Copyright (C) 2025 Cyrille Bagard * @@ -25,7 +25,11 @@ #include "secstorage.h" -#include <core/secstorage.h> +#include <assert.h> +#include <pygobject.h> + + +#include <glibext/secstorage-int.h> #include "../access.h" @@ -34,76 +38,107 @@ -/* Détermine si une clef de chiffrement protégée est en place. */ -static PyObject *py_secstorage_has_secret_storage_key(PyObject *, PyObject *); +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +CREATE_DYN_CONSTRUCTOR(secret_storage, G_TYPE_SECRET_STORAGE); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_secret_storage_init(PyObject *, PyObject *, PyObject *); -/* Définit un mot de passe pour protéger une clef maître. */ -static PyObject *py_secstorage_set_secret_storage_password(PyObject *, PyObject *); -/* Détermine si la clef de chiffrement maître est vérouillée. */ -static PyObject *py_secstorage_is_secret_storage_locked(PyObject *, PyObject *); + +/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ + + +/* Définit un mot de passe pour protéger une clef maître. */ +static PyObject *py_secret_storage_set_password(PyObject *, PyObject *); /* Déverrouille la clef de chiffrement maître. */ -static PyObject *py_secstorage_unlock_secret_storage(PyObject *, PyObject *); +static PyObject *py_secret_storage_unlock(PyObject *, PyObject *); /* Verrouille la clef de chiffrement maître. */ -static PyObject *py_secstorage_lock_secret_storage(PyObject *, PyObject *); +static PyObject *py_secret_storage_lock(PyObject *, PyObject *); /* Chiffre des données avec la clef de chiffrement maître. */ -static PyObject *py_secstorage_encrypt_secret_storage_data(PyObject *, PyObject *); +static PyObject *py_secret_storage_encrypt_data(PyObject *, PyObject *); /* Déchiffre des données avec la clef de chiffrement maître. */ -static PyObject *py_secstorage_decrypt_secret_storage_data(PyObject *, PyObject *); +static PyObject *py_secret_storage_decrypt_data(PyObject *, PyObject *); +/* Détermine si une clef de chiffrement protégée est en place. */ +static PyObject *py_secret_storage_has_key(PyObject *, void *); + +/* Détermine si la clef de chiffrement maître est vérouillée. */ +static PyObject *py_secret_storage_is_locked(PyObject *, void *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : self = objet Python concerné par l'appel. * +* Paramètres : self = objet à initialiser (théoriquement). * * args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * * * -* Description : Détermine si un mot de passe est actuellement en place. * +* Description : Initialise une instance sur la base du dérivé de GObject. * * * -* Retour : Bilan de l'analyse. * +* Retour : 0. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_secstorage_has_secret_storage_key(PyObject *self, PyObject *args) +static int py_secret_storage_init(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *result; /* Conversion à retourner */ GSettings *settings; /* Configuration à considérer */ int ret; /* Bilan de lecture des args. */ - bool status; /* Bilan de situation */ + GSecretStorage *storage; /* Stockage natif à manipuler */ + +#define SECRET_STORAGE_DOC \ + "SecretStorage acts as guardian for secrets using ecryption," \ + " mainly for sensitive information stored as configuration" \ + " parameters.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " SecretStorage(settings)" \ + "\n" \ + "The *settings* arguement must point to a GSettings intance;" \ + " the main configuration settings are used by default." \ -#define SECSTORAGE_HAS_SECRET_STORAGE_KEY_METHOD PYTHON_METHOD_DEF \ -( \ - has_secret_storage_key, "/, settings=None", \ - METH_VARARGS, py_secstorage, \ - "Indicate if a master key used for protecting secrets seems to have"\ - " been defined.\n" \ - "\n" \ - "The *settings* arguement must point to a GSettings intance; the" \ - " main configuration settings are used by default.\n" \ - "\n" \ - "The result is a boolean status: *True* if the master key seems" \ - " to exist, *False* otherwise." \ -) + settings = NULL; - ret = PyArg_ParseTuple(args, "O&", convert_to_gsettings, &settings); - if (!ret) return NULL; + ret = PyArg_ParseTuple(args, "|O&", convert_to_gsettings, &settings); + if (!ret) return -1; - status = has_secret_storage_key(settings); + /* Initialisation d'un objet GLib */ - result = status ? Py_True : Py_False; - Py_INCREF(result); + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; - return result; + /* Eléments de base */ + + storage = G_SECRET_STORAGE(pygobject_get(self)); + + if (!g_secret_storage_create(storage, settings)) + return -1; + + return 0; } + +/* ---------------------------------------------------------------------------------- */ +/* CONNEXION AVEC L'API DE PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * @@ -117,85 +152,35 @@ static PyObject *py_secstorage_has_secret_storage_key(PyObject *self, PyObject * * * ******************************************************************************/ -static PyObject *py_secstorage_set_secret_storage_password(PyObject *self, PyObject *args) +static PyObject *py_secret_storage_set_password(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ - GSettings *settings; /* Configuration à considérer */ const char *passwd; /* Mot de passe associé */ int ret; /* Bilan de lecture des args. */ + GSecretStorage *storage; /* Stockage sécurisé visé */ bool status; /* Bilan de situation */ -#define SECSTORAGE_SET_SECRET_STORAGE_PASSWORD_METHOD PYTHON_METHOD_DEF \ +#define SECRET_STORAGE_SET_PASSWORD_METHOD PYTHON_METHOD_DEF \ ( \ - set_secret_storage_password, "/, settings=None, password=''", \ - METH_VARARGS, py_secstorage, \ + set_password, "/, password=''", \ + METH_VARARGS, py_secret_storage, \ "Create a master key used for protecting secrets. This key is" \ " itself protected by the provided password.\n" \ "\n" \ - "The *settings* arguement must point to a GSettings intance; the" \ - " main configuration settings are used by default. The supplied" \ - " *password* has to be a string.\n" \ + "The supplied *password* has to be a string.\n" \ "\n" \ "The result is a boolean status: *True* if the operation successed,"\ " *False* otherwise." \ ) - settings = NULL; passwd = ""; - ret = PyArg_ParseTuple(args, "|O&s", convert_to_gsettings, &settings, &passwd); + ret = PyArg_ParseTuple(args, "|s", &passwd); if (!ret) return NULL; - status = set_secret_storage_password(settings, passwd); - - result = status ? Py_True : Py_False; - Py_INCREF(result); - - return result; - -} + storage = G_SECRET_STORAGE(pygobject_get(self)); - -/****************************************************************************** -* * -* Paramètres : self = objet Python concerné par l'appel. * -* args = arguments fournis à l'appel. * -* * -* Description : Détermine si la clef de chiffrement maître est vérouillée. * -* * -* Retour : Bilan de la détermination. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_secstorage_is_secret_storage_locked(PyObject *self, PyObject *args) -{ - PyObject *result; /* Conversion à retourner */ - GSettings *settings; /* Configuration à considérer */ - int ret; /* Bilan de lecture des args. */ - bool status; /* Bilan de situation */ - -#define SECSTORAGE_IS_SECRET_STORAGE_LOCKED_METHOD PYTHON_METHOD_DEF \ -( \ - is_secret_storage_locked, "/, settings=None", \ - METH_VARARGS, py_secstorage, \ - "Indicate if the master key used for protecting secrets is" \ - " currently decrypted in memory.\n" \ - "\n" \ - "The *settings* arguement must point to a GSettings intance; the" \ - " main configuration settings are used by default.\n" \ - "\n" \ - "The result is a boolean status: *True* if the master key is" \ - " unlocked and ready for use, *False* otherwise." \ -) - - settings = NULL; - - ret = PyArg_ParseTuple(args, "|O&", convert_to_gsettings, &settings); - if (!ret) return NULL; - - status = is_secret_storage_locked(settings); + status = g_secret_storage_set_password(storage, passwd); result = status ? Py_True : Py_False; Py_INCREF(result); @@ -218,35 +203,35 @@ static PyObject *py_secstorage_is_secret_storage_locked(PyObject *self, PyObject * * ******************************************************************************/ -static PyObject *py_secstorage_unlock_secret_storage(PyObject *self, PyObject *args) +static PyObject *py_secret_storage_unlock(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ - GSettings *settings; /* Configuration à considérer */ const char *passwd; /* Mot de passe associé */ int ret; /* Bilan de lecture des args. */ + GSecretStorage *storage; /* Stockage sécurisé visé */ bool status; /* Bilan de situation */ -#define SECSTORAGE_UNLOCK_SECRET_STORAGE_METHOD PYTHON_METHOD_DEF \ +#define SECRET_STORAGE_UNLOCK_METHOD PYTHON_METHOD_DEF \ ( \ - unlock_secret_storage, "/, settings=None, password=''", \ - METH_VARARGS, py_secstorage, \ + unlock, "/, password=''", \ + METH_VARARGS, py_secret_storage, \ "Decrypt in memory the master key used for protecting secrets.\n" \ "\n" \ - "The *settings* arguement must point to a GSettings intance; the" \ - " main configuration settings are used by default. The supplied" \ - " *password* is the primary password used to protect this key.\n" \ + "The supplied *password* is the primary password used to protect" \ + " this key.\n" \ "\n" \ "The result is a boolean status: *True* if the operation successed" \ " or if the master key is already unlocked, *False* otherwise." \ ) - settings = NULL; passwd = ""; - ret = PyArg_ParseTuple(args, "|O&s", convert_to_gsettings, &settings, &passwd); + ret = PyArg_ParseTuple(args, "|s", &passwd); if (!ret) return NULL; - status = unlock_secret_storage(settings, passwd); + storage = G_SECRET_STORAGE(pygobject_get(self)); + + status = g_secret_storage_unlock(storage, passwd); result = status ? Py_True : Py_False; Py_INCREF(result); @@ -269,28 +254,21 @@ static PyObject *py_secstorage_unlock_secret_storage(PyObject *self, PyObject *a * * ******************************************************************************/ -static PyObject *py_secstorage_lock_secret_storage(PyObject *self, PyObject *args) +static PyObject *py_secret_storage_lock(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ - GSettings *settings; /* Configuration à considérer */ - int ret; /* Bilan de lecture des args. */ + GSecretStorage *storage; /* Stockage sécurisé visé */ -#define SECSTORAGE_LOCK_SECRET_STORAGE_METHOD PYTHON_METHOD_DEF \ -( \ - lock_secret_storage, "/, settings=None", \ - METH_VARARGS, py_secstorage, \ - "Clear from memory the master key used for protecting secrets.\n" \ - "\n" \ - "The *settings* arguement must point to a GSettings intance; the" \ - " main configuration settings are used by default." \ +#define SECRET_STORAGE_LOCK_METHOD PYTHON_METHOD_DEF \ +( \ + lock, "", \ + METH_NOARGS, py_secret_storage, \ + "Clear from memory the master key used for protecting secrets." \ ) - settings = NULL; + storage = G_SECRET_STORAGE(pygobject_get(self)); - ret = PyArg_ParseTuple(args, "|O&", convert_to_gsettings, &settings); - if (!ret) return NULL; - - lock_secret_storage(settings); + g_secret_storage_lock(storage); result = Py_None; Py_INCREF(result); @@ -313,39 +291,38 @@ static PyObject *py_secstorage_lock_secret_storage(PyObject *self, PyObject *arg * * ******************************************************************************/ -static PyObject *py_secstorage_encrypt_secret_storage_data(PyObject *self, PyObject *args) +static PyObject *py_secret_storage_encrypt_data(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ const char *data_in; /* Données d'entrée à chiffrer */ Py_ssize_t size_in; /* Quantité de ces données */ - GSettings *settings; /* Configuration à considérer */ int ret; /* Bilan de lecture des args. */ sized_binary_t in; /* Données à chiffer */ + GSecretStorage *storage; /* Stockage sécurisé visé */ bool status; /* Bilan de situation */ sized_binary_t out; /* Données chiffrées */ -#define SECSTORAGE_ENCRYPT_SECRET_STORAGE_DATA_METHOD PYTHON_METHOD_DEF \ +#define SECRET_STORAGE_ENCRYPT_DATA_METHOD PYTHON_METHOD_DEF \ ( \ - encrypt_secret_storage_data, "data, /, settings=None", \ - METH_VARARGS, py_secstorage, \ + encrypt_data, "data", \ + METH_VARARGS, py_secret_storage, \ "Encrypt data using an unlocked the master key.\n" \ "\n" \ - "The *settings* arguement must point to a GSettings intance; the" \ - " main configuration settings are used by default." \ + "The *data* arguement points to bytes to process." \ "\n" \ - "The result is either encrypted data as bytes in case of success," \ + "The result is either encrypted *data* as bytes in case of success,"\ " or *None* in case of failure." \ ) - settings = NULL; - - ret = PyArg_ParseTuple(args, "s#|O&", &data_in, &size_in, convert_to_gsettings, &settings); + ret = PyArg_ParseTuple(args, "s#", &data_in, &size_in); if (!ret) return NULL; in.static_data = data_in; in.size = size_in; - status = encrypt_secret_storage_data(settings, &in, &out); + storage = G_SECRET_STORAGE(pygobject_get(self)); + + status = g_secret_storage_encrypt_data(storage, &in, &out); if (status) { @@ -377,39 +354,38 @@ static PyObject *py_secstorage_encrypt_secret_storage_data(PyObject *self, PyObj * * ******************************************************************************/ -static PyObject *py_secstorage_decrypt_secret_storage_data(PyObject *self, PyObject *args) +static PyObject *py_secret_storage_decrypt_data(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ const char *data_in; /* Données d'entrée à chiffrer */ Py_ssize_t size_in; /* Quantité de ces données */ - GSettings *settings; /* Configuration à considérer */ int ret; /* Bilan de lecture des args. */ sized_binary_t in; /* Données à chiffer */ + GSecretStorage *storage; /* Stockage sécurisé visé */ bool status; /* Bilan de situation */ sized_binary_t out; /* Données chiffrées */ -#define SECSTORAGE_DECRYPT_SECRET_STORAGE_DATA_METHOD PYTHON_METHOD_DEF \ +#define SECRET_STORAGE_DECRYPT_DATA_METHOD PYTHON_METHOD_DEF \ ( \ - decrypt_secret_storage_data, "data, /, settings=None", \ - METH_VARARGS, py_secstorage, \ + decrypt_data, "data", \ + METH_VARARGS, py_secret_storage, \ "Decrypt data using an unlocked the master key.\n" \ "\n" \ - "The *settings* arguement must point to a GSettings intance; the" \ - " main configuration settings are used by default." \ + "The *data* arguement points to bytes to process." \ "\n" \ - "The result is either decrypted data as bytes in case of success," \ + "The result is either decrypted *data* as bytes in case of success,"\ " or *None* in case of failure." \ ) - settings = NULL; - - ret = PyArg_ParseTuple(args, "s#|O&", &data_in, &size_in, convert_to_gsettings, &settings); + ret = PyArg_ParseTuple(args, "s#", &data_in, &size_in); if (!ret) return NULL; in.static_data = data_in; in.size = size_in; - status = decrypt_secret_storage_data(settings, &in, &out); + storage = G_SECRET_STORAGE(pygobject_get(self)); + + status = g_secret_storage_decrypt_data(storage, &in, &out); if (status) { @@ -430,35 +406,218 @@ static PyObject *py_secstorage_decrypt_secret_storage_data(PyObject *self, PyObj /****************************************************************************** * * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Détermine si une clef de chiffrement protégée est en place. * +* * +* Retour : Bilan de l'analyse. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_secret_storage_has_key(PyObject *self, void *closure) +{ + PyObject *result; /* Instance Python à retourner */ + GSecretStorage *storage; /* Stockage sécurisé visé */ + bool status; /* Bilan de consultation */ + +#define PY_SECRET_STORAGE_HAS_KEY_ATTRIB PYTHON_HAS_DEF_FULL \ +( \ + key, py_secret_storage, \ + "Indicate if a master key used for protecting secrets seems to have"\ + " been defined. Without any unlocking attempt, the test only relies"\ + " on the length of saved master data.\n" \ + "\n" \ + "The returned status is a boolean status: *True* if the master key" \ + " seems to exist, *False* otherwise." \ +) + + storage = G_SECRET_STORAGE(pygobject_get(self)); + + status = g_secret_storage_has_key(storage); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Détermine si la clef de chiffrement maître est vérouillée. * +* * +* Retour : Bilan de la détermination. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_secret_storage_is_locked(PyObject *self, void *closure) +{ + PyObject *result; /* Instance Python à retourner */ + GSecretStorage *storage; /* Stockage sécurisé visé */ + bool status; /* Bilan de consultation */ + +#define SECRET_STORAGE_IS_LOCKED_ATTRIB PYTHON_IS_DEF_FULL \ +( \ + locked, py_secret_storage, \ + "Indicate if the master key used for protecting secrets is" \ + " currently decrypted in memory.\n" \ + "\n" \ + "The *settings* arguement must point to a GSettings intance; the" \ + " main configuration settings are used by default.\n" \ + "\n" \ + "The returned status is a boolean status: *True* if the master key" \ + " is unlocked and ready for use, *False* otherwise." \ +) + + storage = G_SECRET_STORAGE(pygobject_get(self)); + + status = g_secret_storage_is_locked(storage); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * -* Description : Définit une extension du module 'core' à compléter. * +* Description : Fournit un accès à une définition de type à diffuser. * * * -* Retour : Bilan de l'opération. * +* Retour : Définition d'objet pour Python. * * * * Remarques : - * * * ******************************************************************************/ -bool populate_core_module_with_secstorage(void) +PyTypeObject *get_python_secret_storage_type(void) { - bool result; /* Bilan à retourner */ - PyObject *module; /* Module à recompléter */ + static PyMethodDef py_secret_storage_methods[] = { + SECRET_STORAGE_SET_PASSWORD_METHOD, + SECRET_STORAGE_UNLOCK_METHOD, + SECRET_STORAGE_LOCK_METHOD, + SECRET_STORAGE_ENCRYPT_DATA_METHOD, + SECRET_STORAGE_DECRYPT_DATA_METHOD, + { NULL } + }; - static PyMethodDef py_secstorage_methods[] = { - SECSTORAGE_HAS_SECRET_STORAGE_KEY_METHOD, - SECSTORAGE_SET_SECRET_STORAGE_PASSWORD_METHOD, - SECSTORAGE_IS_SECRET_STORAGE_LOCKED_METHOD, - SECSTORAGE_UNLOCK_SECRET_STORAGE_METHOD, - SECSTORAGE_LOCK_SECRET_STORAGE_METHOD, - SECSTORAGE_ENCRYPT_SECRET_STORAGE_DATA_METHOD, - SECSTORAGE_DECRYPT_SECRET_STORAGE_DATA_METHOD, + static PyGetSetDef py_secret_storage_getseters[] = { + PY_SECRET_STORAGE_HAS_KEY_ATTRIB, + SECRET_STORAGE_IS_LOCKED_ATTRIB, { NULL } }; - module = get_access_to_python_module("pychrysalide.core"); + static PyTypeObject py_secret_storage_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.glibext.SecretStorage", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SECRET_STORAGE_DOC, + + .tp_methods = py_secret_storage_methods, + .tp_getset = py_secret_storage_getseters, + + .tp_init = py_secret_storage_init, + .tp_new = py_secret_storage_new, + + }; + + return &py_secret_storage_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.glibext.SecretStorage'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_secret_storage_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'SecretStorage' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_secret_storage_type(); - result = register_python_module_methods(module, py_secstorage_methods); + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.glibext"); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_SECRET_STORAGE, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en gardien des secrets avec stockage. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_secret_storage(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_secret_storage_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to secret storage"); + break; + + case 1: + *((GSecretStorage **)dst) = G_SECRET_STORAGE(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } return result; diff --git a/plugins/pychrysalide/core/secstorage.h b/plugins/pychrysalide/glibext/secstorage.h index d05d052..68726c3 100644 --- a/plugins/pychrysalide/core/secstorage.h +++ b/plugins/pychrysalide/glibext/secstorage.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * secstorage.h - prototypes pour l'équivalent Python du fichier "core/secstorage.h" + * secstorage.h - prototypes pour l'équivalent Python du fichier "glibext/secstorage.h" * * Copyright (C) 2025 Cyrille Bagard * @@ -22,8 +22,8 @@ */ -#ifndef _PLUGINS_PYCHRYSALIDE_CORE_SECSTORAGE_H -#define _PLUGINS_PYCHRYSALIDE_CORE_SECSTORAGE_H +#ifndef _PLUGINS_PYCHRYSALIDE_GLIBEXT_SECSTORAGE_H +#define _PLUGINS_PYCHRYSALIDE_GLIBEXT_SECSTORAGE_H #include <Python.h> @@ -31,9 +31,15 @@ -/* Définit une extension du module 'core' à compléter. */ -bool populate_core_module_with_secstorage(void); +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_secret_storage_type(void); +/* Prend en charge l'objet 'pychrysalide.glibext.SecretStorage'. */ +bool ensure_python_secret_storage_is_registered(void); +/* Tente de convertir en gardien des secrets avec stockage. */ +int convert_to_secret_storage(PyObject *, void *); -#endif /* _PLUGINS_PYCHRYSALIDE_CORE_SECSTORAGE_H */ + + +#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_SECSTORAGE_H */ diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h index 0aaf976..745d013 100644 --- a/plugins/pychrysalide/helpers.h +++ b/plugins/pychrysalide/helpers.h @@ -132,7 +132,7 @@ bool register_python_module_object(PyObject *, PyTypeObject *); PYTHON_GETSET_DEF("is_" #name, base ## _is_ ## name, NULL, ATTRIB_RO doc, NULL) #define PYTHON_HAS_DEF_FULL(name, base, doc) \ - PYTHON_GETSET_DEF(#name, base ## _has_ ## name, NULL, ATTRIB_RO doc, NULL) + PYTHON_GETSET_DEF("has_" #name, base ## _has_ ## name, NULL, ATTRIB_RO doc, NULL) #define PYTHON_RAWGET_DEF_FULL(name, base, doc) \ PYTHON_GETSET_DEF(#name, base ## _ ## name, NULL, ATTRIB_RO doc, NULL) diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 906c383..17fd2bf 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -20,8 +20,7 @@ libcore4_la_SOURCES = \ logs.h logs.c \ nox.h nox.c \ nproc.h nproc.c \ - paths.h paths.c \ - secstorage.h secstorage.c + paths.h paths.c libcore4_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBSSL_CFLAGS) diff --git a/src/core/core.c b/src/core/core.c index eaf7763..8fe12f5 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -25,7 +25,6 @@ #include "global.h" -#include "secstorage.h" @@ -54,7 +53,7 @@ bool load_core_components(AvailableCoreComponent flags) if ((flags & ACC_GLOBAL_VARS) != 0 && (__loaded & ACC_GLOBAL_VARS) == 0) { - init_secret_storage(); + set_secret_storage(g_secret_storage_new(NULL)); set_work_queue(g_work_queue_new()); @@ -85,7 +84,7 @@ void unload_core_components(AvailableCoreComponent flags) { set_work_queue(NULL); - exit_secret_storage(); + set_secret_storage(NULL); __loaded &= ~ACC_GLOBAL_VARS; diff --git a/src/core/global.c b/src/core/global.c index d38656b..0275e09 100644 --- a/src/core/global.c +++ b/src/core/global.c @@ -36,6 +36,9 @@ static size_t _bytes_sent = 0; /* Gestionnaire de tâches parallèles */ static GWorkQueue *_queue = NULL; +/* Gardien des secrets avec support des stockages */ +static GSecretStorage *_storage = NULL; + /****************************************************************************** @@ -131,6 +134,49 @@ GWorkQueue *get_work_queue(void) } +/****************************************************************************** +* * +* Paramètres : queue = nouveau stockage sécurisé à mémoriser ou NULL. * +* * +* Description : Définit le stockage sécurisé principal. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void set_secret_storage(/* __steal */GSecretStorage *storage) +{ + if (_storage != NULL) + unref_object(_storage); + + _storage = storage; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit le stockage sécurisé principal. * +* * +* Retour : Gestionnaire de traitements parallèles courant. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GSecretStorage *get_secret_storage(void) +{ + ref_object(_storage); + + return _storage; + +} + + diff --git a/src/core/global.h b/src/core/global.h index b861ad8..f5d8a62 100644 --- a/src/core/global.h +++ b/src/core/global.h @@ -25,6 +25,7 @@ #define _CORE_GLOBAL_H +#include "../glibext/secstorage.h" #include "../glibext/workqueue.h" @@ -41,6 +42,12 @@ void set_work_queue(/* __steal */GWorkQueue *); /* Fournit le gestionnaire de traitements parallèles courant. */ GWorkQueue *get_work_queue(void); +/* Définit le stockage sécurisé principal. */ +void set_secret_storage(/* __steal */GSecretStorage *); + +/* Fournit le stockage sécurisé principal. */ +GSecretStorage *get_secret_storage(void); + diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index 2e9e86d..81d13d2 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -47,6 +47,8 @@ libglibext_la_SOURCES = \ objhole.h objhole.c \ portion-int.h \ portion.h portion.c \ + secstorage-int.h \ + secstorage.h secstorage.c \ singleton-int.h \ singleton.h singleton.c \ strbuilder-int.h \ diff --git a/src/glibext/secstorage-int.h b/src/glibext/secstorage-int.h new file mode 100644 index 0000000..310fbbc --- /dev/null +++ b/src/glibext/secstorage-int.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * secstorage-int.h - définitions internes pour la conservation sécurisée d'éléments de configuration + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _GLIBEXT_SECSTORAGE_INT_H +#define _GLIBEXT_SECSTORAGE_INT_H + + +#include "secstorage.h" + + + +/* Gardien des secrets avec support des stockages (instance) */ +struct _GSecretStorage +{ + GObject parent; /* A laisser en premier */ + + GSettings *settings; /* Configuration sollicitée */ + + void *master_key; /* Clef déverrouillée */ + +}; + +/* Gardien des secrets avec support des stockages (classe) */ +struct _GSecretStorageClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un gardien des secrets avec support de stockage. */ +bool g_secret_storage_create(GSecretStorage *, GSettings *); + + + +#endif /* _GLIBEXT_SECSTORAGE_INT_H */ diff --git a/src/core/secstorage.c b/src/glibext/secstorage.c index 7f57b1c..84fc10c 100644 --- a/src/core/secstorage.c +++ b/src/glibext/secstorage.c @@ -30,8 +30,8 @@ #include <openssl/rand.h> +#include "secstorage-int.h" #include "../core/logs.h" -#include "../glibext/helpers.h" @@ -71,20 +71,54 @@ #define SECRET_STORAGE_IV_SIZE SECRET_STORAGE_BLOCK_SIZE -/* Conservation des clefs de déchiffrement maîtres par configuration. */ -static GHashTable *__unlocked_keys = NULL; +/* Initialise la classe des stockages de secrets. */ +static void g_secret_storage_class_init(GSecretStorageClass *); -/* Fournit l'espace de configuration réel à manipuler. */ -static GSettings *get_secret_storage_settings(GSettings *); +/* Initialise une instance de stockage de secrets. */ +static void g_secret_storage_init(GSecretStorage *); +/* Supprime toutes les références externes. */ +static void g_secret_storage_dispose(GObject *); + +/* Procède à la libération totale de la mémoire. */ +static void g_secret_storage_finalize(GObject *); + + + +/* Indique le type défini pour un gardien des secrets avec support des stockages. */ +G_DEFINE_TYPE(GSecretStorage, g_secret_storage, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des stockages de secrets. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_secret_storage_class_init(GSecretStorageClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = g_secret_storage_dispose; + object->finalize = g_secret_storage_finalize; + +} /****************************************************************************** * * -* Paramètres : - * +* Paramètres : storage = instance à initialiser. * * * -* Description : Initialise le stockage des clefs de déchiffrement en place. * +* Description : Initialise une instance de stockage de secrets. * * * * Retour : - * * * @@ -92,18 +126,20 @@ static GSettings *get_secret_storage_settings(GSettings *); * * ******************************************************************************/ -void init_secret_storage(void) +static void g_secret_storage_init(GSecretStorage *storage) { - __unlocked_keys = g_hash_table_new_full(g_direct_hash, g_direct_equal, g_object_unref, free); + storage->settings = NULL; + + storage->master_key = NULL; } /****************************************************************************** * * -* Paramètres : - * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Supprime le stockage des clefs de déchiffrement en place. * +* Description : Supprime toutes les références externes. * * * * Retour : - * * * @@ -111,42 +147,97 @@ void init_secret_storage(void) * * ******************************************************************************/ -void exit_secret_storage(void) +static void g_secret_storage_dispose(GObject *object) { - assert(__unlocked_keys != NULL); + GSecretStorage *storage; /* Gestion de stockage sécurisé*/ + + storage = G_SECRET_STORAGE(object); - g_hash_table_remove_all(__unlocked_keys); - g_hash_table_unref(__unlocked_keys); + g_clear_object(&storage->settings); - __unlocked_keys = NULL; + G_OBJECT_CLASS(g_secret_storage_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : settings = éventuel espace de configuration à manipuler. * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Fournit l'espace de configuration réel à manipuler. * +* Description : Procède à la libération totale de la mémoire. * * * -* Retour : Instance de travail à employer avant libération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static GSettings *get_secret_storage_settings(GSettings *settings) +static void g_secret_storage_finalize(GObject *object) { - GSettings *result; /* Instance à retourner */ + GSecretStorage *storage; /* Gestion de stockage sécurisé*/ + + storage = G_SECRET_STORAGE(object); + + if (storage->master_key != NULL) + free(storage->master_key); + + G_OBJECT_CLASS(g_secret_storage_parent_class)->finalize(object); + +} + + +/****************************************************************************** +* * +* Paramètres : settings = éventuel espace de configuration à utiliser. * +* * +* Description : Créé un nouveau gardien des secrets avec support de stockage.* +* * +* Retour : Gestionnaire de stockage sécurisé mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GSecretStorage *g_secret_storage_new(GSettings *settings) +{ + GSecretStorage *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_SECRET_STORAGE, NULL); + if (!g_secret_storage_create(result, settings)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = stockage sécurisé à initialiser. * +* settings = éventuel espace de configuration à utiliser. * +* * +* Description : Met en place un gardien des secrets avec support de stockage.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_secret_storage_create(GSecretStorage *storage, GSettings *settings) +{ + bool result; /* Bilan à retourner */ + + result = true; if (settings != NULL) { ref_object(settings); - result = settings; + storage->settings = settings; } else - result = NULL; // TODO + result = false; // TODO return result; @@ -155,7 +246,7 @@ static GSettings *get_secret_storage_settings(GSettings *settings) /****************************************************************************** * * -* Paramètres : settings = éventuel espace de configuration à manipuler. * +* Paramètres : storage = espace de stockage sécurisé à consulter. * * * * Description : Détermine si une clef de chiffrement protégée est en place. * * * @@ -165,7 +256,7 @@ static GSettings *get_secret_storage_settings(GSettings *settings) * * ******************************************************************************/ -bool has_secret_storage_key(GSettings *settings) +bool g_secret_storage_has_key(const GSecretStorage *storage) { bool result; /* Bilan à retourner */ GVariant *value; /* Valeur de configuration */ @@ -173,10 +264,7 @@ bool has_secret_storage_key(GSettings *settings) result = false; - settings = get_secret_storage_settings(settings); - assert(settings != NULL); - - value = g_settings_get_value(settings, "master"); + value = g_settings_get_value(storage->settings, "master"); g_variant_get_fixed_array(value, &length, 1); @@ -184,8 +272,6 @@ bool has_secret_storage_key(GSettings *settings) g_variant_unref(value); - unref_object(settings); - return result;; } @@ -193,7 +279,7 @@ bool has_secret_storage_key(GSettings *settings) /****************************************************************************** * * -* Paramètres : settings = éventuel espace de configuration à manipuler. * +* Paramètres : storage = espace de stockage sécurisé à consulter. * * password = mot de passe principal à appliquer. * * * * Description : Définit un mot de passe pour protéger une clef maître. * @@ -204,7 +290,7 @@ bool has_secret_storage_key(GSettings *settings) * * ******************************************************************************/ -bool set_secret_storage_password(GSettings *settings, const char *passwd) +bool g_secret_storage_set_password(const GSecretStorage *storage, const char *passwd) { bool result; /* Bilan à retourner */ unsigned char salt[SECRET_STORAGE_SALT_SIZE]; /* Sel pour la dérivation*/ @@ -220,10 +306,7 @@ bool set_secret_storage_password(GSettings *settings, const char *passwd) result = false; - settings = get_secret_storage_settings(settings); - assert(settings != NULL); - - if (has_secret_storage_key(settings)) + if (g_secret_storage_has_key(storage)) goto exit; /* Création d'un sel pour la dérivation du mot de passe */ @@ -250,7 +333,7 @@ bool set_secret_storage_password(GSettings *settings, const char *passwd) * Il n'y a donc pas lieu d'appeler g_variant_unref(). */ - g_settings_set_value(settings, "salt", value); + g_settings_set_value(storage->settings, "salt", value); /* Dérivation du mot de passe */ @@ -329,7 +412,7 @@ bool set_secret_storage_password(GSettings *settings, const char *passwd) value = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, encrypted, iter - encrypted, sizeof(unsigned char)); - g_settings_set_value(settings, "master", value); + g_settings_set_value(storage->settings, "master", value); result = true; @@ -339,8 +422,6 @@ bool set_secret_storage_password(GSettings *settings, const char *passwd) exit: - unref_object(settings); - return result; } @@ -348,7 +429,7 @@ bool set_secret_storage_password(GSettings *settings, const char *passwd) /****************************************************************************** * * -* Paramètres : settings = éventuel espace de configuration à manipuler. * +* Paramètres : storage = espace de stockage sécurisé à consulter. * * * * Description : Détermine si la clef de chiffrement maître est vérouillée. * * * @@ -358,16 +439,11 @@ bool set_secret_storage_password(GSettings *settings, const char *passwd) * * ******************************************************************************/ -bool is_secret_storage_locked(GSettings *settings) +bool g_secret_storage_is_locked(const GSecretStorage *storage) { bool result; /* Bilan à retourner */ - settings = get_secret_storage_settings(settings); - assert(settings != NULL); - - result = (g_hash_table_lookup(__unlocked_keys, settings) == NULL); - - unref_object(settings); + result = (storage->master_key == NULL); return result; @@ -376,7 +452,7 @@ bool is_secret_storage_locked(GSettings *settings) /****************************************************************************** * * -* Paramètres : settings = éventuel espace de configuration à manipuler. * +* Paramètres : storage = espace de stockage sécurisé à manipuler. * * password = mot de passe principal à utiliser. * * * * Description : Déverrouille la clef de chiffrement maître. * @@ -387,7 +463,7 @@ bool is_secret_storage_locked(GSettings *settings) * * ******************************************************************************/ -bool unlock_secret_storage(GSettings *settings, const char *passwd) +bool g_secret_storage_unlock(GSecretStorage *storage, const char *passwd) { bool result; /* Bilan à retourner */ GVariant *salt_value; /* Valeur du sel configuré */ @@ -403,17 +479,10 @@ bool unlock_secret_storage(GSettings *settings, const char *passwd) unsigned char key[SECRET_STORAGE_KEY_SIZE]; /* Clef maître */ unsigned char *iter; /* Tête d'écriture */ int outlen; /* Taille des données utiles */ - void *unlocked; /* Zone de conservation */ -#ifndef NDEBUG - gboolean new; /* Validation de la création */ -#endif result = false; - settings = get_secret_storage_settings(settings); - assert(settings != NULL); - - if (!is_secret_storage_locked(settings)) + if (!g_secret_storage_is_locked(storage)) { result = true; goto quick_exit; @@ -421,7 +490,7 @@ bool unlock_secret_storage(GSettings *settings, const char *passwd) /* Récupération du sel mis en place */ - salt_value = g_settings_get_value(settings, "salt"); + salt_value = g_settings_get_value(storage->settings, "salt"); salt = g_variant_get_fixed_array(salt_value, &salt_length, sizeof(bin_t)); @@ -443,7 +512,7 @@ bool unlock_secret_storage(GSettings *settings, const char *passwd) /* Récupération des paramètres chiffrés */ - enc_value = g_settings_get_value(settings, "master"); + enc_value = g_settings_get_value(storage->settings, "master"); encrypted = g_variant_get_fixed_array(enc_value, &enc_length, sizeof(bin_t)); @@ -495,17 +564,8 @@ bool unlock_secret_storage(GSettings *settings, const char *passwd) /* Stockage de la clef maître en mémoire */ - ref_object(settings); - - unlocked = malloc(SECRET_STORAGE_KEY_SIZE); - memcpy(unlocked, key, SECRET_STORAGE_KEY_SIZE); - -#ifndef NDEBUG - new = g_hash_table_replace(__unlocked_keys, settings, unlocked); - assert(new); -#else - g_hash_table_replace(__unlocked_keys, settings, unlocked); -#endif + storage->master_key = malloc(SECRET_STORAGE_KEY_SIZE); + memcpy(storage->master_key, key, SECRET_STORAGE_KEY_SIZE); result = true; @@ -525,8 +585,6 @@ bool unlock_secret_storage(GSettings *settings, const char *passwd) quick_exit: - unref_object(settings); - return result; } @@ -534,7 +592,7 @@ bool unlock_secret_storage(GSettings *settings, const char *passwd) /****************************************************************************** * * -* Paramètres : settings = éventuel espace de configuration à manipuler. * +* Paramètres : storage = espace de stockage sécurisé à manipuler. * * * * Description : Verrouille la clef de chiffrement maître. * * * @@ -544,23 +602,22 @@ bool unlock_secret_storage(GSettings *settings, const char *passwd) * * ******************************************************************************/ -void lock_secret_storage(GSettings *settings) +void g_secret_storage_lock(GSecretStorage *storage) { - settings = get_secret_storage_settings(settings); - assert(settings != NULL); - - g_hash_table_remove(__unlocked_keys, settings); - - unref_object(settings); + if (storage->master_key != NULL) + { + free(storage->master_key); + storage->master_key = NULL; + } } /****************************************************************************** * * -* Paramètres : settings = éventuel espace de configuration à manipuler. * -* in = séquence d'octets à traiter. * -* out = séquence d'octets résultantes. [OUT] * +* Paramètres : storage = espace de stockage sécurisé à consulter. * +* in = séquence d'octets à traiter. * +* out = séquence d'octets résultantes. [OUT] * * * * Description : Chiffre des données avec la clef de chiffrement maître. * * * @@ -570,10 +627,9 @@ void lock_secret_storage(GSettings *settings) * * ******************************************************************************/ -bool encrypt_secret_storage_data(GSettings *settings, const sized_binary_t *in, sized_binary_t *out) +bool g_secret_storage_encrypt_data(const GSecretStorage *storage, const sized_binary_t *in, sized_binary_t *out) { bool result; /* Bilan à retourner */ - gpointer key; /* Clef de chiffrement */ unsigned char iv[SECRET_STORAGE_IV_SIZE]; /* IV associé */ int ret; /* Bilan à d'un appel */ EVP_CIPHER_CTX *ctx; /* Contexte pour le chiffrement*/ @@ -583,16 +639,11 @@ bool encrypt_secret_storage_data(GSettings *settings, const sized_binary_t *in, result = false; - settings = get_secret_storage_settings(settings); - assert(settings != NULL); - - if (is_secret_storage_locked(settings)) + if (g_secret_storage_is_locked(storage)) goto quick_exit; /* Récupération de la clef maître et d'un IV de chiffrement */ - key = g_hash_table_lookup(__unlocked_keys, settings); - ret = RAND_bytes(iv, sizeof(iv)); if (ret != 1) { @@ -616,7 +667,7 @@ bool encrypt_secret_storage_data(GSettings *settings, const sized_binary_t *in, goto exit; } - ret = EVP_EncryptInit_ex2(ctx, EVP_aes_256_cbc(), key, iv, NULL); + ret = EVP_EncryptInit_ex2(ctx, EVP_aes_256_cbc(), storage->master_key, iv, NULL); if (ret != 1) { LOG_ERROR_OPENSSL; @@ -661,8 +712,6 @@ bool encrypt_secret_storage_data(GSettings *settings, const sized_binary_t *in, exit: quick_exit: - unref_object(settings); - return result; } @@ -670,9 +719,9 @@ bool encrypt_secret_storage_data(GSettings *settings, const sized_binary_t *in, /****************************************************************************** * * -* Paramètres : settings = éventuel espace de configuration à manipuler. * -* in = séquence d'octets à traiter. * -* out = séquence d'octets résultantes. [OUT] * +* Paramètres : storage = espace de stockage sécurisé à consulter. * +* in = séquence d'octets à traiter. * +* out = séquence d'octets résultantes. [OUT] * * * * Description : Déchiffre des données avec la clef de chiffrement maître. * * * @@ -682,10 +731,9 @@ bool encrypt_secret_storage_data(GSettings *settings, const sized_binary_t *in, * * ******************************************************************************/ -bool decrypt_secret_storage_data(GSettings *settings, const sized_binary_t *in, sized_binary_t *out) +bool g_secret_storage_decrypt_data(const GSecretStorage *storage, const sized_binary_t *in, sized_binary_t *out) { bool result; /* Bilan à retourner */ - gpointer key; /* Clef de chiffrement */ unsigned char iv[SECRET_STORAGE_IV_SIZE]; /* IV associé */ int ret; /* Bilan à d'un appel */ EVP_CIPHER_CTX *ctx; /* Contexte pour le chiffrement*/ @@ -695,15 +743,10 @@ bool decrypt_secret_storage_data(GSettings *settings, const sized_binary_t *in, result = false; - settings = get_secret_storage_settings(settings); - assert(settings != NULL); - - if (is_secret_storage_locked(settings)) + if (g_secret_storage_is_locked(storage)) goto quick_exit; - /* Récupération de la clef maître et d'un IV de chiffrement */ - - key = g_hash_table_lookup(__unlocked_keys, settings); + /* Récupération d'un IV de déchiffrement */ if (in->size < SECRET_STORAGE_IV_SIZE) goto exit; @@ -726,7 +769,7 @@ bool decrypt_secret_storage_data(GSettings *settings, const sized_binary_t *in, goto exit; } - ret = EVP_DecryptInit_ex2(ctx, EVP_aes_256_cbc(), key, iv, NULL); + ret = EVP_DecryptInit_ex2(ctx, EVP_aes_256_cbc(), storage->master_key, iv, NULL); if (ret != 1) { LOG_ERROR_OPENSSL; @@ -772,8 +815,6 @@ bool decrypt_secret_storage_data(GSettings *settings, const sized_binary_t *in, exit: quick_exit: - unref_object(settings); - return result; } diff --git a/src/core/secstorage.h b/src/glibext/secstorage.h index 7c27e07..a75b1a3 100644 --- a/src/core/secstorage.h +++ b/src/glibext/secstorage.h @@ -21,45 +21,48 @@ */ -#ifndef _CORE_SECSTORAGE_H -#define _CORE_SECSTORAGE_H +#ifndef _GLIBEXT_SECSTORAGE_H +#define _GLIBEXT_SECSTORAGE_H #include <stdbool.h> #include <gio/gio.h> +#include "helpers.h" #include "../common/szbin.h" -/* Initialise le stockage des clefs de déchiffrement en place. */ -void init_secret_storage(void); +#define G_TYPE_SECRET_STORAGE (g_secret_storage_get_type()) -/* Supprime le stockage des clefs de déchiffrement en place. */ -void exit_secret_storage(void); +DECLARE_GTYPE(GSecretStorage, g_secret_storage, G, SECRET_STORAGE); + + +/* Créé un nouveau gardien des secrets avec support de stockage. */ +GSecretStorage *g_secret_storage_new(GSettings *); /* Détermine si une clef de chiffrement protégée est en place. */ -bool has_secret_storage_key(GSettings *); +bool g_secret_storage_has_key(const GSecretStorage *); /* Définit un mot de passe pour protéger une clef maître. */ -bool set_secret_storage_password(GSettings *, const char *); +bool g_secret_storage_set_password(const GSecretStorage *, const char *); /* Détermine si la clef de chiffrement maître est vérouillée. */ -bool is_secret_storage_locked(GSettings *); +bool g_secret_storage_is_locked(const GSecretStorage *); /* Déverrouille la clef de chiffrement maître. */ -bool unlock_secret_storage(GSettings *, const char *); +bool g_secret_storage_unlock(GSecretStorage *, const char *); /* Verrouille la clef de chiffrement maître. */ -void lock_secret_storage(GSettings *); +void g_secret_storage_lock(GSecretStorage *); /* Chiffre des données avec la clef de chiffrement maître. */ -bool encrypt_secret_storage_data(GSettings *, const sized_binary_t *, sized_binary_t *); +bool g_secret_storage_encrypt_data(const GSecretStorage *, const sized_binary_t *, sized_binary_t *); /* Déchiffre des données avec la clef de chiffrement maître. */ -bool decrypt_secret_storage_data(GSettings *, const sized_binary_t *, sized_binary_t *); +bool g_secret_storage_decrypt_data(const GSecretStorage *, const sized_binary_t *, sized_binary_t *); -#endif /* _CORE_SECSTORAGE_H */ +#endif /* _GLIBEXT_SECSTORAGE_H */ diff --git a/tests/core/re.chrysalide.tests.secstorage.gschema.xml b/tests/glibext/re.chrysalide.tests.secstorage.gschema.xml index 6afa96b..6afa96b 100644 --- a/tests/core/re.chrysalide.tests.secstorage.gschema.xml +++ b/tests/glibext/re.chrysalide.tests.secstorage.gschema.xml diff --git a/tests/core/secstorage.py b/tests/glibext/secstorage.py index 1f82388..248b3e3 100644 --- a/tests/core/secstorage.py +++ b/tests/glibext/secstorage.py @@ -4,8 +4,8 @@ import os import subprocess from chrysacase import ChrysalideTestCase -from pychrysalide import core from gi.repository import Gio, GLib +from pychrysalide.glibext import SecretStorage class TestSecretStorage(ChrysalideTestCase): @@ -47,19 +47,21 @@ class TestSecretStorage(ChrysalideTestCase): settings = Gio.Settings.new('re.chrysalide.tests.secstorage') + storage = SecretStorage(settings) + settings.reset('master') self.assertEqual(len(settings.get_value('master').unpack()), 0) - self.assertFalse(core.has_secret_storage_key(settings)) + self.assertFalse(storage.has_key) settings.set_value('master', GLib.Variant('ay', b'ABC')) - self.assertFalse(core.has_secret_storage_key(settings)) + self.assertFalse(storage.has_key) settings.set_value('master', GLib.Variant('ay', b'A' * 23)) - self.assertTrue(core.has_secret_storage_key(settings)) + self.assertTrue(storage.has_key) def testMasterKeyCreation(self): @@ -67,46 +69,35 @@ class TestSecretStorage(ChrysalideTestCase): settings = Gio.Settings.new('re.chrysalide.tests.secstorage') + storage = SecretStorage(settings) + settings.reset('salt') settings.reset('master') - status = core.has_secret_storage_key(settings) + self.assertFalse(storage.has_key) - self.assertFalse(status); - - status = core.set_secret_storage_password(settings, '') + status = storage.set_password('') self.assertTrue(status); - status = core.has_secret_storage_key(settings) - - self.assertTrue(status); + self.assertTrue(storage.has_key) + self.assertTrue(storage.is_locked) - status = core.is_secret_storage_locked(settings) + status = storage.unlock('') self.assertTrue(status) - status = core.unlock_secret_storage(settings, '') - - self.assertTrue(status) + self.assertFalse(storage.is_locked) - status = core.is_secret_storage_locked(settings) + storage.lock() - self.assertFalse(status) + self.assertTrue(storage.is_locked) - core.lock_secret_storage(settings) - - status = core.is_secret_storage_locked(settings) - - self.assertTrue(status) - - status = core.unlock_secret_storage(settings, 'XXX') + status = storage.unlock('XXX') self.assertFalse(status) - status = core.is_secret_storage_locked(settings) - - self.assertTrue(status) + self.assertTrue(storage.is_locked) def testDataEncryption(self): @@ -114,25 +105,27 @@ class TestSecretStorage(ChrysalideTestCase): settings = Gio.Settings.new('re.chrysalide.tests.secstorage') + storage = SecretStorage(settings) + settings.reset('salt') settings.reset('master') - status = core.set_secret_storage_password(settings, '<s3cUre>') + status = storage.set_password('<s3cUre>') self.assertTrue(status); - status = core.unlock_secret_storage(settings, '<s3cUre>') + status = storage.unlock('<s3cUre>') self.assertTrue(status) original = b'ABC' - encrypted = core.encrypt_secret_storage_data(original, settings) + encrypted = storage.encrypt_data(original) self.assertIsNotNone(encrypted) - plain = core.decrypt_secret_storage_data(encrypted, settings) + plain = storage.decrypt_data(encrypted) self.assertIsNotNone(plain) self.assertEqual(original, plain) @@ -140,11 +133,11 @@ class TestSecretStorage(ChrysalideTestCase): original = b'A' * 136 - encrypted = core.encrypt_secret_storage_data(original, settings) + encrypted = storage.encrypt_data(original) self.assertIsNotNone(encrypted) - plain = core.decrypt_secret_storage_data(encrypted, settings) + plain = storage.decrypt_data(encrypted) self.assertIsNotNone(plain) self.assertEqual(original, plain) |