L’integrità dei dati

In questo articolo utilizzeremo il sistema CRC (Cyclic Redundancy Check) per realizzare un programma che permette di controllare il trasferimento di una nostra applicazione. In realtà questo programma è costituito da due parti: una parte residente su host, un normale personal computer, e l’altra su target. La necessità di utilizzare sistemi che permettono di garantire il trasferimento  corretto di programmi è un’esigenza stringente anche per via dell’integrazione delle applicazioni embedded con internet e, in genere, per esigenze di sicurezza; infatti, in questa maniera possiamo essere sicuri che il nostro file presente sulla memoria del nostro target non potrà essere modificato, in modo arbitrario, da nessuno. Utilizzando questo sistema sarà possibile trasferire, in maniera sicura, i nostri eseguibili su target per essere utilizzati per le nostre esigenze più svariate (figura 1 e 2). Le figure 1 e 2 mostrano i diversi passi per calcolare un CRC. La figura 1 mette in evidenza i passi per calcolarlo utilizzando un polinomio generatore 101, mentre la figura 2 mostra un messaggio con un errore.

Figura 1. calcolo del CRC.

Figura 1. calcolo del CRC.

 

Figura 2. errore su CRC

Figura 2. errore su CRC

Realizzazione del tool

L’utility che proponiamo, chiamata MakeCheck, calcolerà il  checksum di un programma. Per completare il lavoro sarà poi necessario corredarlo con un’altra porzione di codice che permetterà di inserire, in coda alla nostra applicazione, il valore così calcolato.  L’algoritmo di checksum si baserà su un CRC32, ma in ogni caso, in linea di massima, qualsiasi polinomio può andare benissimo. Questo valore di CRC in coda alla nostra applicazione ci permetterà di firmare il file: abbiamo così l’assicurazione della sua integrità. Successivamente possiamo pensare di mettere la nostra applicazione in memoria non volatile (per esempio una memoria di tipo flash) se, e solo se, l’esito di VerifyCheck, listato 2, ha avuto esito positivo. Questa porzione di codice deve risiedere su target ed è parte del programma che deve curarne la sua memorizzazione. Eventualmente,  la porzione di memoria del target non utilizzata dovrà essere riempita con 0xffffffff.

Il progetto

Per implementare l’algoritmo, si veda il listato 1, è utilizzata una tabella di valori già calcolati per aumentarne le prestazioni: questa tabella può essere scaricata dal sito della rivista.

/*
* Compilation unit name: check_tool
 * Compilation unit version number: 1.0
* Description:
              the main routine read the parameters given when
the executable is invoked
*/

static unsigned long CRC32(unsigned long chksum_length,
        char* buffer, unsigned long buffer_length)
{
        unsigned long current_crc, i;
        unsigned char index, value;
        current_crc = 0xffffffff;
        for (i=0; i < chksum_length; i++)
        {
               if (i < buffer_length)
               value = (unsigned char)buffer[i];
               else
               value = 0xff;

       index = value ^ (current_crc & 0x000000ff);
       current_crc = ((current_crc >> 8) & 0x00ffffff) ^
crc_table[index];
       }

       return (~current_crc);
}
Listato 1
/*
* Compilation unit name: verify_tool
 * Compilation unit version number: 1.0
 */
uint32 VerifyChecksum(unsigned char* image, uint32 len, uint8
                               modality, unsigned int PadSize)
{
   /* local variables*/

   uint32 lenght = len;
   uint32 current = 0xFFFFFFFFu;
   uint8 currentIndex = 0u;
   uint8 * currentDWord;
   int32 counter = 0;

   currentDWord = image;

   if (lenght <= PadSize)
   {
     //Read all the file and when it is finished continue up to
     //PadSize-4 bytes using 0xff as value
   for (counter = 0; counter < PadSize-4; counter++)
     {
     if (counter<lenght)
     currentIndex = currentDWord[counter] ^ (current & 0x000000FFu );
     else
     currentIndex = 0xFF ^ (current & 0x000000FFu );

     current = ( (current>>8u) & 0x00FFFFFFu ) ^
                       CRCTable[currentIndex];
   }

   }

   return ~current;

} /* VerifyChecksum */
Listato 2

Il  listato 1 implementa l’algoritmo CRC32, mentre il listato 2 mostra la porzione di codice utilizzata per la verifica su target dell’applicazione. Solo se i due valori di checksum coincidono dovrà essere eseguita la successiva operazione di memorizzazione su target. Chiaramente i due programmi devono utilizzare la stessa tabella CRC32. Si è scelto di utilizzare il linguaggio  C per la stesura di questi due programmi, inoltre, questi non fanno uso di chiamate particolari di sistema, ma solo normali servizi che una qualsiasi libreria C standard dispone. Queste scelte rendono i due programmi portabili verso qualsiasi piattaforma. Per implementare  il checksum seguiamo questi accorgimenti:

  • consideriamo tutti i bytes contenuti nel file da trattare;
  • su tutti i dati estratti e tutti i bytes, occorre calcolare il CRC32 secondo il seguente polinomio generatore:

  • inizializziamo  il valore corrente del checksum, CRC_VALUE, a 0xFFFFFFFF;
  • per ogni byte estratto dal file verrà applicato il seguente  algoritmo:

CURRENT_INDEX = (CURRENT BYTE to be processed) XOR (CRC_VALUE AND 16#000000FF)

CRC_VALUE = ((CRC_VALUE >> 8) AND 6#00FFFFFF) XOR CRC32Table[CURRENT_INDEX]

  • l’algoritmo si conclude invertendo tutti i byte: FINAL_CRC_VALUE = NOT (CRC_VALUE)

 

Scarica subito una copia gratis

Una risposta

  1. Maurizio Di Paolo Emilio Maurizio 27 Novembre 2016

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend