Intégration d’un nouveau chiffre symétrique dans le kernel linux

Dans cet article, nous allons décrire étape par étape les différentes modifications à apporter au noyau Linux pour y ajouter un nouvel algorithme de chiffrement symétrique et ce en visant notamment d’utiliser ce dernier dans la pile IPSec.

Les modifications sont effectuées sur une machine Ubuntu 14.04 (mais sont facilement adaptables aux autres distributions).

  1. Téléchargement, Compilation et Installation du noyau linux

– Télécharger la dernière version stable du noyau Linux sur www.kernel.org (dans la suite de cet article nous considèrerons Linux-3.12.36 comme la dernière version stable).
– Décompresser le code source téléchargé

%> tar linux-3.12.36.tar.xz
%> cd linux-3.12.36

Afin de pouvoir compiler correctement le noyau, certains outils doivent être installés sur  le système :
– Lancer la commande suivante  en tant que root

%> apt-get install ncurses-dev kernel-package fakeroot

– Copier la configuration du noyau dans le répertoire du nouveau kernel.

%> cp /boot/config-‘uname -r‘ /path/to/new/kernel/.config

– Lancer le menu de configuration du noyau

%> make menuconfig

Une fois le menu disponible, choisir « Load » et choisir .config comme fichier de configuration.

Une fois ces étapes accomplies, nous sommes prêts à compiler le nouveau noyau.

– Pour compiler le noyau, exécuter les 2 commandes suivantes

%>make-kpkg clean
%>fakeroot make-kpkg --initrd --append-to-version=-cryptobourrin-version kernel_image kernel_headers

Une fois la compilation terminée (ce qui peut prendre un peu de temps), le nouveau kernel peut-être installé :

%>dpkg -i linux-image-3.12.36-cryptobourrin-version_3.12.36-cryptobourrin-version-10.00.Custom_amd64.deb

Ce paquet contient les fichiers nécessaires pour de futures compilations.

  • Optionnel: modifier le GRUB afin de pouvoir démarrer directement en utilisant le noyau fraichement compilé.

– Redémarrer votre machine avec le nouveau noyau.

%>reboot

Si toutes ces étapes se sont déroulées sans erreur, la suivante consiste donc à modifier le kernel pour y ajouter toutes les références nécessaires au chiffre FOO puis le recompiler.

  1. Configuration du Kernel

Pour déclarer un nouvel algorithme symétrique dans la pile IPSec du noyau, ce dernier étant bien conçu, il y a peu de chose à faire.

– Editer les fichiers xfrm_algo.c et pfkeyv2.c et rajouter une référence au chiffre FOO en s’inspirant par exemple de ce qui a été fait pour l’AES.
Ici nous rajoutons la déclaration de notre chiffre en mode CBC.

%>vim path/to/linux-3.12.36/net/xfrm/xfrm_algo.c
{
 .name = cbc(foocipher),
 .compat = foocipher,
 .uinfo = {
   .encr = {
     .blockbits = 128, //Taille du bloc en bit
     .defkeybits = 256,//Taille par défaut de la clé en bit
           }

          },

 .desc = {
   .sadb_alg_id = SADB_X_EALG_FOOCIPHERCBC,
   .sadb_alg_ivlen = 8, 
   .sadb_alg_minbits = 128, //Taille minimale de la clé supportée
   .sadb_alg_maxbits = 256 //Taille maximale de la clé supportée
         }
 },

Et définir l’identifiant de notre algorithme conformément à la RFC 2407 et suivante (voir IANA)

%>vim path/to/linux-3.12.36/include/uapi/linux/pfkeyv2.h

#define SADB_X_EALG_FOOCIPHERCBC 1024 //Algo propriétaire 

  1. Création et chargement du module “FOO Cipher” dans le noyau

En s’inspirant de ce qui est fait pour les autres algorithmes de chiffrement symétrique, créer le code source du module foocipher.

  • Importer le code source dans le répertoire crytpo
%>vim path/to/linux-3.12.36/crypto/foocipher_generic.c

#define FOOCIPHER_MIN_KEY_SIZE       16
#define FOOCIPHER_MAX_KEY_SIZE       32
#define FOOCIPHER_BLOCK_SIZE         16

struct foocipher_ctx {
       int key_length;
};

static int foocipher_set_key(struct crypto_tfm *tfm, const u8 *in_key,
                unsigned int key_len)
{

       return 0;
}
static void foocipher_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
       const __be32 *src = (const __be32 *)in;
       __be32 *dst = (__be32 *)out;
       u32 tmp[4];

       tmp[0] = be32_to_cpu(src[0]);
       tmp[1] = be32_to_cpu(src[1]);
       tmp[2] = be32_to_cpu(src[2]);
       tmp[3] = be32_to_cpu(src[3]);
       //DO what modification you want
       dst[0] = cpu_to_be32(tmp[0]);
       dst[1] = cpu_to_be32(tmp[1]);
       dst[2] = cpu_to_be32(tmp[2]);
       dst[3] = cpu_to_be32(tmp[3]);
}
static void foocipher_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
       const __be32 *src = (const __be32 *)in;
       __be32 *dst = (__be32 *)out;
       u32 tmp[4];
       tmp[0] = be32_to_cpu(src[0]);
       tmp[1] = be32_to_cpu(src[1]);
       tmp[2] = be32_to_cpu(src[2]);
       tmp[3] = be32_to_cpu(src[3]);
       //DO what modification you want
       dst[0] = cpu_to_be32(tmp[0]);
       dst[1] = cpu_to_be32(tmp[1]);
       dst[2] = cpu_to_be32(tmp[2]);
       dst[3] = cpu_to_be32(tmp[3]);
}

static struct crypto_alg foocipher_alg = {
       .cra_name               =       "foocipher",
       .cra_driver_name       =       "foocipher-generic",
       .cra_priority           =       100,
       .cra_flags             =       CRYPTO_ALG_TYPE_CIPHER,
       .cra_blocksize         =       FOOCIPHER_BLOCK_SIZE,
       .cra_ctxsize           =       sizeof(struct foocipher_ctx),
       .cra_alignmask         =       3,
       .cra_module             =       THIS_MODULE,
       .cra_u                 =       {
               .cipher = {
                       .cia_min_keysize       =       FOOCIPHER_MIN_KEY_SIZE,
                       .cia_max_keysize       =       FOOCIPHER_MAX_KEY_SIZE,
                       .cia_setkey             =       foocipher_set_key,
                       .cia_encrypt           =       foocipher_encrypt,
                       .cia_decrypt           =       foocipher_decrypt
               }
        }
};

static int __init foocipher_init(void)
{
       return crypto_register_alg(&foocipher_alg);
}

static void __exit foocipher_fini(void)
{
       crypto_unregister_alg(&foocipher_alg);
}

module_init(foocipher_init);
module_exit(foocipher_fini);

MODULE_DESCRIPTION("Foocipher Cipher Algorithm");
MODULE_LICENSE("GPL");
MODULE_ALIAS("foocipher");
  • Ajouter des références dans les différents fichiers de configuration
%> vim path/to/linux-3.12.36/.config
%> vim path/to/linux-3.12.36/crypto/Kconfig
%> vim path/to/linux-3.12.36/crypto/Makefile
  • Compiler le code source pour générer le module noyau “foocipher.ko” (s’assurer que les headers utilisés sont les bons)
%> make all
  • Lancer la commande insmod command afin de charger le module dans le noyau
%>insmod foocipher.ko
  • Lister les modules chargés dans le noyau
%>lsmod
  • Vérifier que le module FOOCIPHER est présent dans la liste

foocipherEt vous voilà prêt pour monter un tunnel IPSEC en utilisant votre chiffre foocipher.

Publicités

A propos JoMendes

Amateur de mathématiques et d'hexadécimal. Je m'intéresse de près ou de loin suivant mon niveau à tous les sujets de sécurité de l'information.
Cet article, publié dans Cryptographie Symétrique, est tagué , , . Ajoutez ce permalien à vos favoris.

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s