Fortify har postat på sin blogg om en undersökning av säkerheten i referensimplementationerna av SHA-3-kandidaterna.
Fortify har använt sitt verktyg Fortify SCA, en linter speciellt utvecklad för att hitta kodmässiga svagheter som buffertöverskrivningar etc. (Det hade antagligen gått bra att använda splint eller liknande säkerhetsinriktade lintverktyg för att hitta svagheterna.)
Vad Fortify upptäckt är att ett antal av SHA-3-kandidaterna har mer eller mindre allvarliga svagheter i sin implementation, mer specifikt i Blender, Crunch, FSB, MD6, Vortex. Några typiska fel är att koden tillåter buffertöverskrivningar, att den läser utanför gränserna i en buffert (indexeringsfel) och minnesläckage. Som ett exempel tar Fortify upp MD6:
One of the projects with buffer issues was MD6, the implementation provided Professor Ron Rivest and his team. All of the problems came back to the hashval field of the md6_state struct:
unsigned char hashval[ (md6_c/2)*(md6_w/8) ];
The buffer size is determined by two constants:
#define w md6_w /* # bits in a word (64) */
#define c md6_c /* # words in compression output (16) */
At several points, this buffer is read or written to using a different bound:
if (z==1) /* save final chaining value in st->hashval */
{ memcpy( st->hashval, C, md6_c*(w/8) );
return MD6_SUCCESS;
}
Further analysis showed that ANSI standard layout rules would make incorrect behavior unlikely, but other compilers may have allowed it to be exploited. The MD6 team has doubled the size of the vulnerable buffer, which eliminated the risk. In this case, Fortify SCA found an issue that would have been difficult to catch otherwise.
The other buffer overflow was found in the Blender implementation, from Dr. Colin Bradbury. This issue was a classic typo:
DataLength sourceDataLength2[3];// high order parts of data length
...
if (ss.sourceDataLength < (bcount | databitlen)) // overflow
if (++ss.sourceDataLength2[0] 0) // increment higher order count
if (++ss.sourceDataLength2[1] 0) // and the next higher order
++ss.sourceDataLength2[3]; // and the next one, etc.
The developer simply mistyped, using 3 instead of 2 for the array access. This issue was probably not caught because it would not be exposed without a very large input. The other issues we found were memory leaks and null dereferences from memory allocation.
Att den här typen av programmeringsfel kan få betydelse för SHA-3-tävlingen är uppenbart, och illustreras tydligt med MD6. Dess internbuffert behövde dubbleras i storlek. Detta gör att implementationer av MD6 för inbyggda system kommer att kräva mer minnesresurser än vad tidigare angetts. En av styrkorna med MD6 enligt dess skapare är att den skalar extremt bra ner till mycket små implementationer, och det argumentet fick sig nu nog en liten törn.
Ett annat skäl till varför jag tycker att Fortifys undersökning är bra är att referensimplementationer ofta används i applikationer. Antingen direkt eller som bas (funktionell referens) för en ny implementation. Därmed riskerar svagheter i referensimplementationen att sprida sig. Fortify tar själva upp ett exempel från en svaghet i referensimplementationen av RSA som lett till buggar i olika SSL-implementationer.
I fallet SHA-3, med dess fokus på prestanda, vilket gjort att skaparna av kandidater slitit och sliter med att optimera ut varenda cykel de kan ur sin kod, tror jag att referensimplementationer kommer att få stor användning i applikationskod.