        Verification independante du fonctionnement d'IPSec sous FreeBSD

  David Honig

   <honig@sprynet.com>

   Version: 8def749c53

   FreeBSD is a registered trademark of the FreeBSD Foundation.

   Motif, OSF/1, and UNIX are registered trademarks and IT DialTone and The
   Open Group are trademarks of The Open Group in the United States and other
   countries.

   Many of the designations used by manufacturers and sellers to distinguish
   their products are claimed as trademarks. Where those designations appear
   in this document, and the FreeBSD Project was aware of the trademark
   claim, the designations have been followed by the << (TM) >> or the
   << (R) >> symbol.

   2013-11-13 07:52:45 +0000 par Hiroki Sato.
   Resume

   Vous avez installe IPSec et cela semble fonctionner. Comment pouvez-vous
   en etre sur? Je decris une methode pour verifier experimentalement le
   fonctionnement d'IPSec.

   Version franc,aise de Marc Fonvieille <blackend@FreeBSD.org>.

   [ Multiples pages HTML / Page HTML unique ]

     ----------------------------------------------------------------------

   Table des matieres

   1. Le probleme

   2. La solution

   3. L'experience

   4. Mise en garde

   5. IPSec - Definition

   6. Installation d'IPSec

   7. src/sys/i386/conf/KERNELNAME

   8. Test statistique universel de Maurer (pour une longueur de bloc=8 bits)

1. Le probleme

   Tout d'abord, supposons que vous avez installe IPSec. Comment savez-vous
   si cela fonctionne? Bien sur, votre connexion ne fonctionnera pas si elle
   est mal configuree, et fonctionnera quand vous l'aurez enfin correctement
   configuree. netstat(1) le fera apparaitre. Mais pouvez-vous le confirmer
   de fac,on independante?

2. La solution

   Tout d'abord, quelques informations theoriques relatives `a la
   cryptographie:

    1. Les donnees chiffrees sont uniformement distribuees, i.e., ont une
       entropie maximale par symbole;

    2. Les donnees brutes, non compressees sont en generale redondantes,
       i.e., n'ont pas une entropie maximale.

   Supposez que vous pourriez mesurer l'entropie des donnees `a destination
   et en provenance de votre interface reseau. Alors vous pourriez voir la
   difference entre donnees non-chiffees et donnees chiffrees. Cela serait
   vrai meme si certaines des donnees en "mode chiffre" n'etaient pas
   chiffrees --- comme l'en-tete IP externe, si le paquet doit etre routable.

  2.1. MUST

   L'"Universal Statistical Test for Random Bit Generators"( MUST) d'Ueli
   Maurer, ou encore le "test statistique universel pour les generateurs
   aleatoires de bits", mesure rapidement l'entropie d'un echantillon. Il
   utilise une sorte d'algorithme de compression. Le code est donne
   ci-dessous pour une variante qui mesure les morceaux (environ un quart de
   megaoctet) successifs d'un fichier.

  2.2. Tcpdump

   Nous avons egalement besoin d'une maniere de capturer les donnees reseau
   brutes. Un programme appele tcpdump(1) vous permet de faire cela, si vous
   avez active l'interface Berkeley Packet Filter (Filtre de Paquet de
   Berkeley) dans votre fichier de configuration du noyau.

   La commande

 tcpdump -c 4000 -s 10000 -w dumpfile.bin

   capturera 4000 paquets bruts dans le fichier dumpfile.bin. Dans cet
   exemple jusqu'`a 10000 octets par paquets seront captures.

3. L'experience

   Voici l'experience:

    1. Ouvrez une fenetre sur un hote IPSec et une autre sur un hote non
       securise.

    2. Maintenant commencez `a capturer les paquets.

    3. Dans la fenetre "securisee", lancez la commande UNIX(R) yes(1), qui
       fera defiler le caractere y. Au bout d'un moment, arretez cela. Passez
       `a la fenetre non securisee, et faites de meme. Au bout d'un moment,
       arretez.

    4. Maintenant lancez MUST sur les paquets captures. Vous devriez voir
       quelque chose de semblable `a ce qui suit. Ce qui est important de
       noter est que la connexion non securisee a 93% (6,7) de valeurs
       attendues (7,18), et la connexion "normale" a 29% (2,1) de valeurs
       attendues.

 % tcpdump -c 4000 -s 10000 -w ipsecdemo.bin
 % uliscan ipsecdemo.bin

 Uliscan 21 Dec 98
 L=8 256 258560
 Measuring file ipsecdemo.bin
 Init done
 Expected value for L=8 is 7.1836656
 6.9396 --------------------------------------------------------
 6.6177 -----------------------------------------------------
 6.4100 ---------------------------------------------------
 2.1101 -----------------
 2.0838 -----------------
 2.0983 -----------------

4. Mise en garde

   Cette experience montre qu'IPSec semble distribuer les donnees utiles
   uniformement comme un chiffrement le devrait. Cependant, l'experience
   decrite ici ne peut pas detecter les problemes possibles dans un systeme.
   Ceux-ci peuvent etre la generation ou l'echange d'une cle faible, des
   donnees ou cles visibles par d'autres, l'utilisation d'algorithmes
   faibles, code du noyau modifie, etc... Etudiez les sources, maitrisez le
   code.

5. IPSec - Definition

   Extensions de securite au protocole internet IPv4, requises pour l'IPv6.
   Un protocole pour le chiffrement et l'authentification au niveau IP (hote
   `a hote). SSL securise uniquement une socket d'application; SSH securise
   seulement une session; PGP securise uniquement un fichier specifique ou un
   message. IPSec chiffre tout entre deux hotes.

6. Installation d'IPSec

   La plupart des versions recentes de FreeBSD ont le support IPSec dans
   leurs sources de base. Aussi vous devrez probablement ajouter l'option
   IPSEC dans votre configuration de noyau et, apres la compilation et
   l'installation du noyau, configurer les connexions IPSec en utilisant la
   commande setkey(8).

   Un guide complet sur l'utilisation d'IPSec sous FreeBSD est fourni dans le
   Manuel de Freebsd.

7. src/sys/i386/conf/KERNELNAME

   Ce qui suit doit etre present dans le fichier de configuration du noyau
   afin de pouvoir capturer les donnees reseau avec tcpdump(1). Soyez-sur de
   lancer config(8) apres avoir rajoute la ligne ci-dessous, et de recompiler
   et reinstaller.

 device  bpf

8. Test statistique universel de Maurer (pour une longueur de bloc=8 bits)

   Vous pouvez trouver le meme code source ici.

 /*
   ULISCAN.c   ---blocksize of 8

   1 Oct 98
   1 Dec 98
   21 Dec 98       uliscan.c derived from ueli8.c

   This version has // comments removed for Sun cc

   This implements Ueli M Maurer's "Universal Statistical Test for Random
   Bit Generators" using L=8

   Accepts a filename on the command line; writes its results, with other
   info, to stdout.

   Handles input file exhaustion gracefully.

   Ref: J. Cryptology v 5 no 2, 1992 pp 89-105
   also on the web somewhere, which is where I found it.

   -David Honig
   honig@sprynet.com

   Usage:
   ULISCAN filename
   outputs to stdout
 */

 #define L 8
 #define V (1<<L)
 #define Q (10*V)
 #define K (100   *Q)
 #define MAXSAMP (Q + K)

 #include <stdio.h>
 #include <math.h>

 int main(argc, argv)
 int argc;
 char **argv;
 {
   FILE *fptr;
   int i,j;
   int b, c;
   int table[V];
   double sum = 0.0;
   int iproduct = 1;
   int run;

   extern double   log(/* double x */);

   printf("Uliscan 21 Dec 98 \nL=%d %d %d \n", L, V, MAXSAMP);

   if (argc < 2) {
     printf("Usage: Uliscan filename\n");
     exit(-1);
   } else {
     printf("Measuring file %s\n", argv[1]);
   }

   fptr = fopen(argv[1],"rb");

   if (fptr == NULL) {
     printf("Can't find %s\n", argv[1]);
     exit(-1);
   }

   for (i = 0; i < V; i++) {
     table[i] = 0;
   }

   for (i = 0; i < Q; i++) {
     b = fgetc(fptr);
     table[b] = i;
   }

   printf("Init done\n");

   printf("Expected value for L=8 is 7.1836656\n");

   run = 1;

   while (run) {
     sum = 0.0;
     iproduct = 1;

     if (run)
       for (i = Q; run && i < Q + K; i++) {
         j = i;
         b = fgetc(fptr);

         if (b < 0)
           run = 0;

         if (run) {
           if (table[b] > j)
             j += K;

           sum += log((double)(j-table[b]));

           table[b] = i;
         }
       }

     if (!run)
       printf("Premature end of file; read %d blocks.\n", i - Q);

     sum = (sum/((double)(i - Q))) /  log(2.0);
     printf("%4.4f ", sum);

     for (i = 0; i < (int)(sum*8.0 + 0.50); i++)
       printf("-");

     printf("\n");

     /* refill initial table */
     if (0) {
       for (i = 0; i < Q; i++) {
         b = fgetc(fptr);
         if (b < 0) {
           run = 0;
         } else {
           table[b] = i;
         }
       }
     }
   }
 }
